这个问题分为两部分:
InputStream i1 = new InputStream()
和new InputStream()
之间的区别是什么?
和
创建所有局部变量仅仅是为了关闭它们是否值得?
我知道简单的答案,第一个你可以保留变量,继续使用变量甚至关闭输入流就像一个优秀的程序员。第二个你失去了它的参考,但它看起来更简洁。这两者之间有什么记忆差异吗?速度差(毁灭性)怎么样?
现在举例说明了我的想法。首先,我们使用`'new Object()`而无需抛弃它。
public void getLongStrings() throws IOException {
try {
foo = FileCopyUtils.copyToString(new InputStreamReader(aBook.getInputStream()));
bar = FileCopyUtils.copyToString(new InputStreamReader(aNovel.getInputStream()));
}
catch (IOException ioe) {
//do something appropriate here;
}
}
现在更详细的方法
public void getLongStrings() throws IOException {
InputStream i1 = null;
InputStream i2 = null;
InputStreamReader isr1 = null;
InputStreamReader isr2 = null;
try {
i1 = aBook.getInputStream();
i2 = aNovel.getInputStream();
isr1 = new InputStreamReader(i1);
isr2 = new InputStreamReader(i2);
foo = FileCopyUtils.copyToString(isr1);
bar = FileCopyUtils.copyToString(isr2);
}
catch (IOException ioe) {
//do something appropriate here
} finally {
if (i1 != null) i1.close();
if (i2 != null) i2.close();
if (isr1 != null) isr1.close();
if (isr2 != null) isr2.close();
}
}
第一个还是第二个更好?一个比另一个快吗?即使看起来不漂亮,关闭我所有的流是否明智?
感谢您提供任何见解(或修改)。
答案 0 :(得分:7)
第二个你失去了它的参考,但它看起来更简洁。
是的,它更简洁。你对这个对象做的很少 - 重要的是,你没有做应该做的事情。采用快捷方式通常会产生较少的代码,但是通过在终结器关闭之前保持打开文件句柄,您会发现您将获得难以可靠再现的异常。
两者之间是否有任何记忆差异?
也许,但那不相关。这里重要的资源不是内存,而是文件句柄。
速度差异(破坏中)怎么样?
再次,可能是无关紧要的。正确性更为重要。
(请注意,您当前的第二个代码仍然不完全可靠 - 如果其中一个早期close()
调用引发异常,则不会关闭其余代码。)
如果您使用的是Java 7,则应该查看try-with-resources statement,这会使所有这些变得更加简单。
编辑:正如JB Nizet的回答所述,你正在使用的代码可能已经关闭了基础流 - 这取决于FileCopyUtils
是什么。如果是Spring课程,你没事。如果它是其他东西,你可能不是。你应该阅读文档。一般原则如上所述:您应确保某事关闭流。不要认为只是因为在这种情况下你不需要明确地关闭事物,这在一般情况下是正确的。
请注意,Guava的InputSupplier
和OutputSupplier
接口在这里非常有用 - 它允许您在知道输入/输出尚未打开的情况下传递供应商然而 ...这意味着其他代码可以执行打开/复制/关闭(或任何需要的)并为您处理所有...您最终不会使用代码中的任何对象< em>可以关闭。
答案 1 :(得分:4)
假设这是Spring的FileCopyUtils,its javadoc说:
所有复制方法使用4096字节的块大小,并在完成后关闭所有受影响的流。
(强调我的)
因此,在这种情况下,您的初始方法非常好:Spring处理Reader的关闭,关闭Reader关闭包装的流。
如果不是这种情况,则必须关闭Reader,最好使用Java 7的尝试使用资源。
请注意,您的第二个示例关闭了流但不必关闭:关闭阅读器会自动关闭它。另请注意,如果第一个阅读器无法关闭并抛出IOException,则第二个阅读器将无法正确关闭。使用尝试使用资源的另一个好理由是保证关闭所有内容。
答案 2 :(得分:1)
假设FileCopyUtils.copyToString()
不关闭提供的流,则第二种方法更好。
close()
来释放与该流相关的任何资源。所以这不是代码漂亮或性能的问题,而是正确性。
第二种方法有一个错误,当任何close
次调用抛出异常时,所有剩余的close()
次调用都不会被调用。