Java资源管理:了解Findbugs的结果

Findbugs告诉我一个打开两个Closeable实例的方法,但我无法理解为什么。

资源

 public static void sourceXmlToBeautifiedXml(File input, File output) throws TransformerException, IOException, JAXBException { FileReader fileReader = new FileReader(input); FileWriter fileWriter = new FileWriter(output); try { // may throw something sourceXmlToBeautifiedXml(fileReader, fileWriter); } finally { try { fileReader.close(); } finally { fileWriter.close(); } } } 

Findbugs分析

Findbugs告诉我

 Method [...] may fail to clean up java.io.Reader [...] 

并指向FileReader fileReader = ...

谁错了:我还是Findbugs?

FindBugs是正确的:如果FileWriter的构造函数抛出exception,则不会关闭文件阅读器。 要validation这一点,请尝试传递无效的文件名以进行output

我会这样做:

  FileReader fileReader = new FileReader(input); try { FileWriter fileWriter = new FileWriter(output); try { // may throw something sourceXmlToBeautifiedXml(fileReader, fileWriter); } finally { fileWriter.close(); } } finally { fileReader.close(); } 

请注意,关闭时抛出exception的处理可以得到改进,因为通过抛出exception来保留finally块将导致try-statement通过抛出该exception来终止,吞掉try-block中抛出的任何exception,这通常是对调试更有用。 有关如何避免这种情况的简单方法,请参阅duffymo的答案。

编辑 :从Java 7开始,我们可以使用try-with-resources语句,该语句允许对这些极端情况进行正确和精细的处理:

 try ( FileReader fileReader = new FileReader(input); FileWriter fileWriter = new FileWriter(output) ) { // may throw something sourceXmlToBeautifiedXml(fileReader, fileWriter); } 

即使对于虫子来说,这也许很复杂。

 try { fileReader.close(); } finally { fileWriter.close(); } 

在我看来你是对的。

编辑 :哇,我以为我会因为说findbugs错了而被罚下来!

编辑 :看起来像FindBugs是正确的。 好赶上meriton。

我会说是你。

我将在一个单独的try / catch块中关闭这两个资源。 我会创建静态方法来帮助我:

 public static void sourceXmlToBeautifiedXml(File input, File output) throws TransformerException, IOException, JAXBException { FileReader fileReader = new FileReader(input); FileWriter fileWriter = new FileWriter(output); try { // may throw something sourceXmlToBeautifiedXml(fileReader, fileWriter); } finally { close(fileReader); close(fileWriter); } } // same for reader & writer public static void close(InputStream s) { try { if (s != null) { s.close(); } } catch (IOException e) { e.printStackTrace(); } } 

我认为findbugs是对的。

 } finally { try { fileReader.close(); } finally { fileWriter.close(); } } 

在此块中,您尝试关闭FileReader。 但是这可以抛出一个exception,最后在嵌套中关闭fileWriter。 您是否尝试在同一块块中关闭两个读取器? 那个findbugs说什么呢?

 } finally { try { fileReader.close(); fileWriter.close(); } finally { //dunno maybe log that something went wrong. } }