实现Closeable或实现AutoCloseable

问题描述 投票:106回答:6

我正在学习Java,我找不到关于implements Closeableimplements AutoCloseable接口的任何好的解释。

当我实现interface Closeable时,我的Eclipse IDE创建了一个方法public void close() throws IOException

我可以使用没有界面的pw.close();关闭流。但是,我无法理解如何使用接口实现close()方法。而且,这个界面的目的是什么?

另外我想知道:我如何检查IOstream是否真的关闭了?

我正在使用下面的基本代码

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 {


}
java java-io
6个回答
31
投票

在我看来,你对界面不是很熟悉。在您发布的代码中,您不需要实现AutoCloseable

如果您要实现自己的Closeable(处理文件或需要关闭的任何其他资源),您只需(或应该)实现AutoCloseablePrintWriter

在您的实现中,只需调用pw.close()即可。你应该在finally块中执行此操作:

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) {
      }
   }
}

上面的代码与Java 6相关。在Java 7中,这可以更优雅地完成(参见this answer)。


161
投票

AutoCloseable(在Java 7中引入)使得使用try-with-resources成语成为可能:

public class MyResource implements AutoCloseable {

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

}

现在你可以说:

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

并且JVM会自动为您调用close()

Closeable是一个较旧的界面。 由于某些原因 为了保持向后兼容性,语言设计者决定创建一个单独的兼容性。这不仅允许所有Closeable类(如投掷IOException的流)在try-with-resources中使用,而且还允许从close()抛出更多一般的检查异常。

如有疑问,请使用AutoCloseable,贵班的用户将不胜感激。


62
投票

Closeable扩展了AutoCloseable,专门用于IO流:它抛出IOException而不是Exception,并且是幂等的,而AutoCloseable不提供这种保证。

这两个接口的javadoc都解释了这一点。

实现AutoCloseable(或Closeable)允许将一个类用作Java 7中引入的try-with-resources构造的资源,该构造允许在块结束时自动关闭这些资源,而不必添加关闭的finally块。资源明确。

您的类不代表可关闭的资源,并且实现此接口绝对没有意义:无法关闭IOTest。它甚至不可能实例化它,因为它没有任何实例方法。请记住,实现接口意味着类和接口之间存在is-a关系。你在这里没有这样的关系。


6
投票

这是一个小例子

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 ");
    }
}

这是输出:

GeneralTest 
From Close -  AutoCloseable  
From Final Block

5
投票

try-with-resources声明。

try-with-resources statement是一个try声明,声明一个或多个资源。 resource是一个在程序完成后必须关闭的对象。 try-with-resources statement确保在语句结束时关闭每个资源。任何实现java.lang.AutoCloseable的对象(包括实现java.io.Closeable的所有对象)都可以用作资源。

以下示例从文件中读取第一行。它使用BufferedReader实例从文件中读取数据。 BufferedReader是一个必须在程序完成后关闭的资源:

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

在此示例中,try-with-resources语句中声明的资源是BufferedReader。声明语句出现在try关键字后面的括号内。 Java SE 7及更高版本中的类BufferedReader实现了接口java.lang.AutoCloseable。因为BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是正常还是突然完成(由于BufferedReader.readLine方法抛出IOException),它都将被关闭。

在Java SE 7之前,无论try语句是正常还是突然完成,您都可以使用finally块来确保关闭资源。以下示例使用finally块而不是try-with-resources语句:

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

}

refer to the docs


1
投票

最近我读了一本Java SE 8 Programmer Guide ii Book。

我发现了AutoCloseable与Closeable之间的区别。

AutoCloseable接口是在Java 7中引入的。在此之前,存在另一个名为Closeable的接口。它与语言设计者想要的类似,但有以下例外:

  • Closeable限制抛出到IOException的异常类型。
  • Closeable要求实现是幂等的。

语言设计者强调向后兼容性。由于不希望更改现有接口,因此他们创建了一个名为AutoCloseable的新接口。这个新界面不如Closeable严格。由于Closeable满足AutoCloseable的要求,因此在引入后者时开始实现AutoCloseable。

© www.soinside.com 2019 - 2024. All rights reserved.