28

Update: As @PaulGroke points out below, things have changed with Java 7: there now is AutoCloseable. Which isn't tied to streams and supported by the new try-with-resources construct.

AutoCloseable is the direct Java equivalent for .NET's IDisposable interface.


The Closeable interface introduced in Java 1.5 is tightly tied to streams, and even has an exception specifier for IOException. This suggests that it should only be used for streams or other IO related activities, rather than general purpose cleanup logic.

Certainly the description for the close() method would make absolutely no sense outside of a stream/IO context:

void close() throws IOException

Closes this stream and releases any system resources associated with it.

Should I therefore declare my own interface, Disposable, with a Dispose() method on it, and use that as an analogue to .NET's IDisposable interface? Or should I re-use Closeable even though it may not be a perfect fit?

4

3 回答 3

45

我相信大多数人都知道这一点,但是由于在搜索“IDisposable Java”时这个问题仍然是排名靠前的结果(我刚才的第 2 个结果),而且这里仍然没有提到它......

Java 7 发生了变化:现在有了AutoCloseable。它与流无关,并由新的try-with-resources构造支持。

于 2013-03-16T02:47:31.060 回答
17

特别是考虑到 close() 抛出一个 IOException ,然后您必须为其编写异常处理代码,我建议您编写自己的接口。然后,此接口可以抛出任何适合您要放置该接口的用途的已检查异常。

接口倾向于在读者的脑海中表示意图,因此让一个类实现与 IO 相关的 Closeable 接口将使读者假设该类也是基于 IO 的。

显然,如果你确实要关闭的对象都是IO 相关的,你应该使用 Closeable。但否则去

/** Interface for objects that require cleanup post-use. Call dispose() in finally block! */
public interface Disposable {
    public void dispose();
}
于 2009-07-22T14:13:58.333 回答
1

在类中实现Closeable(或AutoClosable就此而言)时,也可以省略 throws 声明:

class X implements Closeable {
    @Override public void close() /* I don't throw */ {

    }
}

因此,当有人使用类型化对象时,他们可以调用close()而无需捕获任何内容:

void f() { // notice no need for throws because close() doesn't throw
    X x = new X();
    try {
        // do something
    } finally {
        x.close();
    }
}

它也与任何期望 a 的东西兼容Closeable:如果这个对象被传递到某个处理的地方Closeable,他们已经预料到一个异常并正确处理它,尽管在这种情况下是徒劳的。

正如 Paul Groke 所建议的,这包括Guava和 Java 7 try-with-resources 等库:Closeables

try (X x = new X()) {
    // do something
}

但是有一个罕见的警告:一旦被剥离,您就不能在子类中重新引入异常:

class Y extends X {
                                  /* compile error */
    @Override public void close() throws IOException {
        // Y.close clashes with X.close: overridden method does not throw IOException
    }
}
于 2016-04-20T10:49:30.390 回答