通常只关闭最外层的流是可以的,因为按照惯例,它必须在底层流上触发关闭。
所以通常代码是这样的:
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
...
in.close(); // when you care about Exception-Handling in case when closing fails
}
finally {
IOUtils.closeQuietly(in); // ensure closing; Apache Commons IO
}
尽管如此,在极少数情况下,底层流构造函数会在流已打开的情况下引发异常。在这种情况下,上面的代码不会关闭底层流,因为从未调用外部构造函数并且in 为空。因此,finally 块不会关闭任何东西,从而使底层流处于打开状态。
从 Java 7 开始,您可以这样做:
try (OutputStream out1 = new ...; OutputStream out2 = new ...) {
...
out1.close(); //if you want Exceptions-Handling; otherwise skip this
out2.close(); //if you want Exceptions-Handling; otherwise skip this
} // out1 and out2 are auto-closed when leaving this block
在大多数情况下,您不希望在关闭时引发异常处理,因此请跳过这些显式 close() 调用。
编辑
下面是一些非信徒的代码,在这些代码中使用这种模式非常重要。您可能还想阅读有关 closeQuietly() 方法的 Apache Commons IOUtils javadoc。
OutputStream out1 = null;
OutputStream out2 = null;
try {
out1 = new ...;
out2 = new ...;
...
out1.close(); // can be skipped if we do not care about exception-handling while closing
out2.close(); // can be skipped if we ...
}
finally {
/*
* I've some custom methods in my projects overloading these
* closeQuietly() methods with a 2nd param taking a logger instance,
* because usually I do not want to react on Exceptions during close
* but want to see it in the logs when it happened.
*/
IOUtils.closeQuietly(out1);
IOUtils.closeQuietly(out2);
}
当out2 的创建引发异常时,使用@Tom 的“建议”将使out1 保持打开状态。这个建议来自有人谈论It's a continual source of errors for obvious reasons. 好吧,我可能是盲人,但这对我来说并不明显。在我能想到的每个用例中,我的模式都是白痴安全的,而 Tom 的模式容易出错。