开放流try / finally块的Java代码样式

时间:2011-01-18 18:05:51

标签: java coding-style

这是一个代码风格的问题。我注意到很多示例代码,包括一些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风格在在线示例中非常常见,我想知道我的是否有一些隐藏错误。

我对InputStreamOutputStreamjava.sql.Connectionjava.sql.PreparedStatement等问同样的问题。我倾向于获取try块之外的资源,然后在finally中关闭它而不进行空检查。除了文体差异之外,还有什么我想念的吗?

感谢。

8 个答案:

答案 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()trycatch内发生的任何错误。

答案 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)

我通常do this

InputStream in = null;
try { 
  in = acquire();
  ...
} finally { 
   if( in != null ) try {
       in.close();
    } catch( IOException ioe ) {
       // ignore exception while closing
    }
}

在关闭资源时,可能会抛出异常,在这种情况下你需要一个额外的try / catch,但是大多数时候我可以忽略它(我毕竟是关闭它)但是这个是唯一的地方我使用if没有大括号。

我很久以前就从Huckster code看到了这一点。