假设您需要打开的不是一个文件,而是两个文件。你会做
final InputStream in = new FileInputStream(file1);
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
in.close();
}
如果out
打开失败,你会得到一个异常,因为它在try
块外in
不会被关闭在finally
块中。
在另一种方法中:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
if (out != null) out.close();
if (in != null) in.close();
}
如果out
无法打开,您将转到finally
块并关闭两个流。如果in
打开失败,你将进入 finally 块,并且只释放in
- 因为out==null
.
编辑
正如 aetheria 所提到的,该代码无法正常工作,因为close()
在 Java 中会引发异常。它可以通过将每个资源释放放在它自己的块中来轻松try
修复catch
:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
try{ out.close(); }catch(Exception e){}
try{ in.close(); }catch(Exception e){}
}
我放弃了空检查 - 如果in
orout
为空,它会抛出一个NullPointerException
将被忽略的。我忽略close
异常的原因是处理方法首先不应该抛出异常。如果需要处理关闭异常,您始终可以在块之后再次关闭流。finally
这样,任何可以关闭的流都将已经关闭(因此您不必担心),并且您可以close
更优雅地处理任何异常。
现在,aetheria 还建议为每个资源放置一个单独的try
-finally
块,如下所示:
final InputStream in = new FileInputStream(file1);
try {
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
}
} finally {
in.close();
}
这行得通,但即使只有两个资源,它也不那么优雅,因为它拆分了分配和释放代码,使得跟踪它变得更加困难(至少在我看来)。