29

据我所知,Closeable接口是从 Java 1.5 开始的,而AutoCloseable是在 Java 1.7 中引入的。
我想了解的是为什么 Closeable扩展AutoCloseable 而不是反之亦然?这样做是因为向后依赖(无法更改 Closeable 接口),即 AutoCloseable 需要比 Closeable 更广泛的异常吗?还是我的逻辑是错误的,应该是这样?

4

4 回答 4

34

这样,所有自动实现的用户代码Closeable都可以实现AutoCloseable,这使他们能够自动受益于 try-with-resources 语法。

于 2013-10-24T17:27:55.217 回答
27

@Sotirios Delimanolis 的评论已经确定了。

Java 7 团队想要一种机制来将对象标记为可自动关闭以用于“使用资源尝试”构造。不幸的是,该方法的 API 规范Closeable.close()过于严格。它要求close()方法是幂等的……但这在“使用资源尝试”用例中不是必需的。

因此,他们引入了语义AutoClosable限制较少的接口close()……并将其改装CloseableAutoCloseable.

另一件事是AutoCloseable.close()声明为 throwingException而不是IOException. 这意味着AutoCloseableAPI 比Closeable... 限制更少,并且鉴于它在 try-with-resources 中有效地用作回调API,这使其更灵活/更广泛适用。(API 可用于与 I/O 无关的资源,但仍可能在关闭时抛出异常。)另一方面,如果close() throws Exception方法已被注入,Java 类型将不允许他们进行此类更改进入子类型。


替代方案是:

  • 将“尝试资源”限制为具有幂等关闭的资源......这限制了它的有用性,或者

  • 回顾性地改变Closeable.close()...的语义,这可能会导致人们难以将旧代码移植到 Java 7

  • 追溯更改Closeable.close()... 的签名,这将破坏二进制兼容性。

于 2013-10-24T17:34:09.820 回答
2

Closeable接口是在 Java 5 中引入的。当try-with-resources(以下是示例代码)在 Java 7 中引入时,语言设计者想要更改一些东西但需要向后兼容(所有在以前版本中编写的代码不应随着引入而过时新功能)也因此他们创建了一个AutoCloseable具有他们想要的规则的超级界面。

使用资源尝试的示例:

    try (NewResource a = NewResource.CreateResource();
{
    }

上面的代码是尝试资源。我们可以简单地理解为,在这段代码中,我们可以在 try 代码中声明一个新变量本身,并且该变量可以调用代码中的其他方法。除了减少try块的冗长之外,这段代码也不需要 finally 块,但执行环境应该是 Java 7 或更高版本。虽然 finally 是 JVM 自己创建的。

closeable&Autocloseable接口只包含一种方法

void close()

而throws的close ()方法,则closeablethrowsIOException的方法。Autocloseableclose()Exception

于 2016-11-02T18:59:07.437 回答
0

Closeable有一些限制,因为它只能 throw IOException,所以在不破坏遗留代码的情况下不能改变它。所以AutoCloseable被介绍了,它可以抛出Exception.

AutoCloseable用于使用 >JDK7 的应用程序。

由于 JDK7+ 库的使用AutoCloseable和实现的遗留代码Closeable仍然需要与 JDK7+ 兼容,因此使 Closeable 扩展了 AutoCloseable。

public interface Closeable extends AutoCloseable {
    public void close() throws IOException;
}

AutoCloseable专门设计用于使用 try-with-resources 语句。与Closeableextends一样AutoCloseable,try-with-resources 可用于关闭任何实现 Closeable 或 AutoCloseable 的资源。

于 2017-08-26T01:26:02.983 回答