Closeable'ı uygular veya AutoCloseable'ı uygular


129

Java öğrenme sürecindeyim implements Closeableve implements AutoCloseablearayüzler hakkında iyi bir açıklama bulamıyorum .

Bir uyguladığımda interface Closeable, Eclipse IDE'm bir yöntem oluşturdu public void close() throws IOException.

pw.close();Arayüzü kullanmadan akışı kapatabilirim . Ancak, close()arayüzü kullanarak yöntemi nasıl uygulayabileceğimi anlayamıyorum . Ve bu arayüzün amacı nedir?

Ayrıca bilmek istiyorum: IOstreamgerçekten kapalı olup olmadığını nasıl kontrol edebilirim ?

Aşağıdaki temel kodu kullanıyordum

import java.io.*;

public class IOtest implements AutoCloseable {

public static void main(String[] args) throws IOException  {

    File file = new File("C:\\test.txt");
    PrintWriter pw = new PrintWriter(file);

    System.out.println("file has been created");

    pw.println("file has been created");

}

@Override
public void close() throws IOException {


}

2
Sanırım her şey zaten söylendi, ancak kaynakların denenmesiyle ilgili şu makale ilginizi çekebilir : docs.oracle.com/javase/tutorial/essential/exceptions/… . Bu, verilen cevapları anlamaya da yardımcı olabilir.
crusam

Yanıtlar:


41

Bana öyle geliyor ki arayüzlere pek aşina değilsiniz. Gönderdiğiniz kodda uygulamanıza gerek yoktur AutoCloseable.

Yalnızca kapatmanız gereken dosyaları veya diğer kaynakları işleyen kendi uygulamanızı uygulamanız (veya yapmanız gerekir) Closeableveya AutoCloseableuygulamak PrintWriterüzereyseniz.

Uygulamanızda aramanız yeterlidir pw.close(). Bunu nihayet blokta yapmalısınız:

PrintWriter pw = null;
try {
   File file = new File("C:\\test.txt");
   pw = new PrintWriter(file);
} catch (IOException e) {
   System.out.println("bad things happen");
} finally {
   if (pw != null) {
      try {
         pw.close();
      } catch (IOException e) {
      }
   }
}

Yukarıdaki kod Java 6 ile ilgilidir. Java 7'de bu daha zarif bir şekilde yapılabilir ( bu yanıta bakın ).


3
Neden sadece a ile PrintWriter? Özellikle AutoClosablenesneler PrintWriters ...
glglgl

3
Kesinlikle haklısın. Soru hakkındaydı, PrintWriterbu yüzden daha spesifik olmasını söyledim.
Kai

7
Java 6'nın durumu neden bağlamında açıklanmalı AutoCloseable? try-with-resources
Onun

191

AutoCloseable(Java 7'de tanıtılmıştır), kaynaklarla dene deyiminin kullanılmasını mümkün kılar :

public class MyResource implements AutoCloseable {

    public void close() throws Exception {
        System.out.println("Closing!");
    }

}

Şimdi şunu söyleyebilirsin:

try (MyResource res = new MyResource()) {
    // use resource here
}

ve JVM close()sizin için otomatik olarak arayacaktır .

Closeable eski bir arayüzdür. Bazı sebeplerden dolayıGeriye dönük uyumluluğu korumak için dil tasarımcıları ayrı bir tane oluşturmaya karar verdiler. Bu, yalnızca tüm Closeablesınıfların (akışlar atma gibi IOException) kaynaklarla denemede kullanılmasına izin vermekle kalmaz, aynı zamanda close().

Şüphe duyduğunuzda kullanın AutoCloseable, sınıfınızın kullanıcıları minnettar olacaktır.


107
Nedeni basit: Closeable.close()atışlar IOException. Bir çok close()kaynak Try-ile-diğer kontrol istisnalar atmak ait yararlanabilecek yöntemlerle (örn java.sql.Connection.close()böylece AutoCloseable.close()atar Exceptionmevcut değiştirme. CloseableTüm mevcut uygulamaları kıracak sözleşme / kütüphane olduğunu sözleşme güvenerek close()sadece atar IOExceptiontüm (işaretli) istisnalar değil.
Mark Rotteveel

4
@MarkRotteveel: +1, teşekkürler. Cevabımı önerilerinizi ve yorumlarınızı yansıtacak şekilde düzelttim.
Tomasz Nurkiewicz

9
Ve ayrıca: Closeable.close()idempotent olması gerekir. AutoCloseable.close()değil, ancak yine de şiddetle tavsiye ediliyor.
Lukas Eder

2
Ayrıca, varsayılanı public void close( ) throws Exceptionkullanmayın - yapabiliyorsanız daha spesifik bir istisna kullanın (
örn.

3
Closeableidempotence garanti etmez . Bu gerektiren bir kullanıcının uygulanmasında idempotence close()yöntemiyle. Ve IOExceptiondaha spesifik / uygun olup olmadığı kullanım durumuna bağlıdır.
xdhmoore

71

Closeablegenişler AutoCloseableve özellikle IO akışlarına adanmıştır: Exception yerine IOException oluşturur ve idempotenttir, oysa AutoCloseable bu garantiyi sağlamaz.

Bunların hepsi her iki arayüzün javadoc'unda açıklanmıştır.

AutoCloseable (veya Closeable) uygulamak, bir sınıfın Java 7'de tanıtılan kaynaklarla dene yapısının bir kaynağı olarak kullanılmasına izin verir, bu da bu tür kaynakların bir bloğun sonunda otomatik olarak kapatan bir blok eklemek zorunda kalmadan kapatılmasına izin verir. kaynak açıkça.

Sınıfınız kapatılabilir bir kaynağı temsil etmiyor ve bu arayüzü uygulamanın kesinlikle bir anlamı yok: bir IOTest kapatılamaz. Herhangi bir örnek yöntemi olmadığı için onu somutlaştırmak bile mümkün olmamalı. Bir arabirim uygulamasının , sınıf ile arabirim arasında bir "bir" ilişkisi olduğu anlamına geldiğini unutmayın . Burada böyle bir ilişkiniz yok.


5
Sadece uygulamak kapanabilir akışları ile ilgili sınıflar için ve AutoClosable kendkapat özelliğini gerektirir diğerleri için.
lospejos

7

İşte küçük örnek

public class TryWithResource {

    public static void main(String[] args) {
        try (TestMe r = new TestMe()) {
            r.generalTest();
        } catch(Exception e) {
            System.out.println("From Exception Block");
        } finally {
            System.out.println("From Final Block");
        }
    }
}



public class TestMe implements AutoCloseable {

    @Override
    public void close() throws Exception {
        System.out.println(" From Close -  AutoCloseable  ");
    }

    public void generalTest() {
        System.out.println(" GeneralTest ");
    }
}

İşte çıktı:

GeneralTest 
From Close -  AutoCloseable  
From Final Block

Çıktıyı da yazmak daha iyidir, böylece bu kadar kısa bir kod için deneme projesine gerek kalmaz.
raxetul

Close () yönteminde, kaynağı açıkça kapatmamıza gerek yok mu? Belki sadece baskı ifadesi vardır.
Shailesh waghmare

@ShaileshWaghmare evet aynen. ancak test amaçlı olarak Kod alıntısında bahsetmiştim.
Lova Chittumuri

@LovaChittumuri Yani this.close()otomatik olarak çağrıldığı için kodda bir şey gibi mi olacak ? (Emin olmak için)
Shailesh Waghmare

@shailesh Waghmare Beni test etmek ister misiniz?
Lova Chittumuri

6

try-with-resourcesBeyanı.

try-with-resources statementBir olan try, bir veya daha fazla kaynak beyan beyanı. A resource, programla bittikten sonra kapatılması gereken bir nesnedir. try-with-resources statementHer kaynak deyimi sonunda kapalı olmasını sağlar. Uygulanan java.lang.AutoCloseabletüm nesneleri içeren , uygulayan herhangi bir nesne java.io.Closeablebir kaynak olarak kullanılabilir.

Aşağıdaki örnek, bir dosyadan ilk satırı okur. BufferedReaderDosyadan veri okumak için bir örnek kullanır . BufferedReaderprogram onunla bittikten sonra kapatılması gereken bir kaynaktır:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

Bu örnekte, kaynakları dene deyiminde bildirilen kaynak bir BufferedReader'dır. Bildirim ifadesi, try anahtar sözcüğünden hemen sonra parantez içinde görünür. BufferedReaderJava SE 7 ve sonraki sürümlerdeki sınıf , arayüzü uygular java.lang.AutoCloseable. Çünkü BufferedReaderörnek bir try-ile-kaynak açıklamada bildirilmiş, ne olursa olsun try deyimi (yöntemin bir sonucu olarak normal veya aniden tamamlar bakılmaksızın kapalı olacak BufferedReader.readLinebir atma IOException).

Java SE 7'den önce finally, try ifadesinin normal veya aniden tamamlanmasına bakılmaksızın bir kaynağın kapatıldığından emin olmak için bir blok kullanabilirsiniz . Aşağıdaki örnek finally, bir try-with-resourcesifade yerine bir blok kullanır :

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }

}

Lütfen belgelere bakın .


6

Yakın zamanda bir Java SE 8 Programcı Kılavuzu ii Kitabı okudum.

AutoCloseableVs arasındaki fark hakkında bir şey buldum Closeable.

AutoCloseableArayüz Bundan önce Java 7. tanıtıldı, başka arayüz denilen varlığından Closeable. Aşağıdaki istisnalar dışında dil tasarımcılarının istediği şeye benziyordu:

  • Closeableatılan istisna türünü kısıtlar IOException.
  • Closeable uygulamaların idempotent olmasını gerektirir.

Dil tasarımcıları geriye dönük uyumluluğu vurgular. Mevcut arayüzü değiştirmek istenmeyen bir durum olduğu için, yeni bir ad yaptılar AutoCloseable. Bu yeni arayüz daha az katıdır Closeable. İçin Closeablegereksinimleri karşıladığından, ikincisi tanıtıldığında AutoCloseableuygulamaya başlamıştır AutoCloseable.


1
"Bu yeni arayüz daha az katıdır Closeable" demek yerine, "Bu yeni arayüz, kapatma sırasında atılan istisnanın mutlaka bir IOException olmadığı daha genel bağlamlarda kullanılabilir" demeyi öneririm. Java evreninde "daha az katı" olmanın olumsuz bir havası vardır.
Fountainhead
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.