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. } }