应该使用Closeable作为.NET的IDisposable的Java等价物吗?

时间:2009-07-22 13:53:28

标签: java idisposable

更新:正如@PaulGroke在下面指出的那样,Java 7已经发生了变化:现在有AutoCloseable。这与新的try-with-resources构造不支持流并且支持。

AutoCloseable是.NET的IDisposable接口的直接Java等价物。


Java 1.5中引入的Closeable接口与流紧密相关,甚至还有IOException的异常说明符。这表明它应该仅用于流或其他IO相关活动,而不是通用清理逻辑。

当然,close()方法的描述在流/ IO上下文之外完全没有意义:

  

void close() throws IOException

     

关闭此流并释放与其关联的所有系统资源。

因此,我是否应该使用Disposable方法声明我自己的接口Dispose(),并将其用作.NET IDisposable接口的模拟?或者我应该重新使用Closeable即使它可能不是一个完美的契合?

3 个答案:

答案 0 :(得分:39)

我确信大多数人都知道这一点,但是因为这个问题仍然是搜索“IDisposable Java”时的最佳结果(我刚刚给出了#2结果),而且这里仍未提及......

Java 7已经发生了变化:现在有AutoCloseable。这与新的try-with-resources构造不支持流并且支持。

答案 1 :(得分:14)

特别是假设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();
}

答案 2 :(得分: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();
    }
}

它还与期望Closeable的任何内容兼容:如果将此对象传递到处理Closeable的某个位置,则它们已经预见到异常并正确处理它,尽管在这种情况下是徒劳的。

这包括像Guava Closeables和Java 7试用资源这样的库,正如Paul Groke建议的那样:

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