这是一个代码风格的问题。我注意到很多示例代码,包括一些examples from Oracle,确保以下列方式关闭流:
InputStream in = null;
try {
in = acquireStream();
...
} finally {
if (in != null) in.close();
}
请注意初始化为null并在finally
块中检查空值。
我倾向于编写这样的代码:
InputStream in = acquireStream();
try {
...
} finally {
in.close();
}
两种方法都有优缺点吗?我喜欢我的风格,因为我不需要空检查。另外,我希望尽可能避免使用null
。但由于Oracle风格在在线示例中非常常见,我想知道我的是否有一些隐藏错误。
我对InputStream
,OutputStream
,java.sql.Connection
,java.sql.PreparedStatement
等问同样的问题。我倾向于获取try
块之外的资源,然后在finally
中关闭它而不进行空检查。除了文体差异之外,还有什么我想念的吗?
感谢。
答案 0 :(得分:8)
从 Java 7 开始,就Closeable
资源编写try-finally块有更好的方法。
现在,您可以在try
关键字后的括号中创建资源,如下所示:
try (init resources) {
...
}
代码块完成后,它们将被关闭 自动 。无需关闭finally
块中的流。
示例:
try (
ZipFile zf = new ZipFile(zipFileName);
BufferedWriter writer = Files.newBufferedWriter(outputFilePath, charset);
) {
// Enumerate each entry
for (Enumeration entries = zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
完成for
循环后,资源将被关闭!
答案 1 :(得分:6)
答案是,不,这样做没有隐藏的错误。这纯粹是一种风格的东西。 我通常从来没有尝试catch finally块,只尝试catch块并尝试finally块。
他们往往看起来像这样:
try {
InputStream in = acquireStream();
try {
...
} finally {
in.close();
}
} catch (IOException e) {
... handle exception
}
没有理由将acquireStream()放在try finally块中。如果in从未分配给有效的流,则永远不能关闭它。显式空检查完全没必要。此外,您很少想要在close()上处理异常,而不是主处理块中的异常。
答案 2 :(得分:3)
通常您所拥有的是try
, catch
,finally
。在这种情况下,使用标准SUN方法是有利的,因为您可以捕获acquireStream()
,try
内catch
内发生的任何错误。
答案 3 :(得分:3)
我会用
InputStream in = null;
try {
in = acquireStream();
...
} finally {
if (in != null) in.close();
}
如果aquireStream()
抛出任何已检查的异常,我打算处理它。
否则,我会用这个
InputStream in = acquireStream();
try {
...
} finally {
in.close();
}
关于NPE :
我宁愿让NPE传播而不处理任何运行时异常。
答案 4 :(得分:2)
我认为在try块中获取流更安全。
还有另一种关闭选项 - 您可以执行以下操作,而不是检查空值:
finally {
IOUtils.closeQuietly(in);
}
这确实需要Apache Commons-IO来执行此操作,但它会为您执行空检查。这样做风格也是一种不错的方式。
答案 5 :(得分:0)
如果您的acquireStream()返回null,当您尝试在finally块中关闭您的流时,您将获得NPE并且它将被取消。
答案 6 :(得分:0)
我赞成第一个。一些I / O操作符要求它们位于try / catch中 某些条件或其他。此外,操作总是可以意外返回null, 即使这不在手册中。
答案 7 :(得分:0)