通常情况下,只关闭最外层流就可以了,因为按照惯例它必须触发底层流的关闭操作。
所以通常的代码看起来像这样:
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
...
in.close();
}
finally {
IOUtils.closeQuietly(in);
}
然而,在一些罕见的情况下,当流已经打开时,底层流构造函数可能会引发异常。在这种情况下,上述代码将无法关闭底层流,因为外部构造函数从未被调用,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()调用。
编辑
以下是一些代码,供那些必须使用此模式的非信徒参考。您可能还想阅读Apache Commons IOUtils javadoc有关
closeQuietly()方法的说明。
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);
}
使用@Tom的“建议”会导致在创建
out2
时引发异常时留下
out1
打开。这个建议来自某个人谈论
它是一个明显错误的持续来源。
嗯,我可能很瞎,但对我来说这不是显而易见的。我的模式在我能想到的每种用例中都是傻瓜安全的,而Tom的模式容易出错。