实现Closeable或实现AutoCloseable

mal*_*las 113 java java-io

我正在学习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 {


}
Run Code Online (Sandbox Code Playgroud)

Tom*_*icz 170

AutoCloseable (在Java 7中引入)使得可以使用try-with-resources习惯用法:

public class MyResource implements AutoCloseable {

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

}
Run Code Online (Sandbox Code Playgroud)

现在你可以说:

try (MyResource res = new MyResource()) {
    // use resource here
}
Run Code Online (Sandbox Code Playgroud)

和JVM将close()自动为您调用.Closeable是一个较旧的界面.由于某些原因为了保持向后兼容性,语言设计者决定创建一个单独的语言 这样,不仅所有Closeable类(如流抛出IOException)都可以在try-with-resources中使用,也可以在那些希望抛出更多常规检查异常的类中使用close().

如有疑问,请使用AutoCloseable,您班级的用户将不胜感激.

  • 原因很简单:`Closeable.close()`抛出`IOException`.许多可以从try-with-resources中受益的`close()`方法抛出其他已检查的异常(例如`java.sql.Connection.close()`所以`AutoCloseable.close()`抛出`异常`.现有的`Closeable`契约会破坏所有现有的应用程序/库,依赖于`close()`只抛出`IOException`而不是所有(已检查)异常的契约. (99认同)
  • 而且:`Closeable.close()`必须是幂等的.`AutoCloseable.close()`不是,尽管仍然强烈推荐. (9认同)
  • @MarkRotteveel:+1,谢谢.我更正了我的回答,以反映您的建议和意见. (4认同)
  • 另外,不要使用默认的`public void close() throws Exception`——如果可以的话,使用更具体的异常(例如IOException) (2认同)
  • `Closeable`不*保证*幂等.它*在用户实现`close()`方法时需要*幂等性.并且`IOException`是否更具体/适当取决于用例. (2认同)
  • 您还可以在 try-with-resources 中使用 Closable,因为 Closable 是 AutoClosable 的子接口 (2认同)

JB *_*zet 68

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

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

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

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

  • 只需为流相关类实现**Closable**,为其他需要autoclose功能的**实现**AutoClosable**. (3认同)

Kai*_*Kai 31

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

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

在你的实现中,它就足够了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) {
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码与Java 6相关.在Java 7中,这可以做得更优雅(参见本答案).

  • 为什么要在"AutoCloseable"的上下文中描述Java 6的情况?更好地展示"尝试用资源"而不是...... (7认同)
  • 为什么只用'PrintWriter`?特别是`AutoClosable`对象可以在更多的情况下使用,而不仅仅是'PrintWriter'... (3认同)
  • 你是绝对正确的.问题是关于'PrintWriter`所以我提到它更具体. (3认同)

Lov*_*uri 7

这是一个小例子

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 ");
    }
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

GeneralTest 
From Close -  AutoCloseable  
From Final Block
Run Code Online (Sandbox Code Playgroud)


ind*_*ine 6

try-with-resources声明.

try-with-resources statementtry声明一个或多个资源的声明.A 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

在Java SE 7之前finally,无论try语句是正常还是突然完成,您都可以使用块来确保关闭资源.以下示例使用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();
    }

}
Run Code Online (Sandbox Code Playgroud)

参阅文档.


Arv*_*tte 5

最近,我阅读了Java SE 8程序员指南ii。

我发现一些有关之间的差异AutoCloseableVS Closeable

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

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

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