更新:正如@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
即使它可能不是一个完美的契合?
答案 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
}
}