Java中的InputStreams和OutputStreams是否在销毁时关闭()?我完全明白这可能是一个糟糕的形式(特别是在C和C++世界),但我很好奇.
另外,假设我有以下代码:
private void foo() { final string file = "bar.txt"; Properties p = new Properties(); p.load( new FileInputStream(file) ); //... }
无名的FileInputStream是否在p.load()之后超出范围,因此被销毁,有点像C++作用域规则?我尝试在Google上搜索java的匿名变量范围,但这并没有达到我认为的那样.
谢谢.
第一个答案:Java中没有"破坏"(在C++意义上).只有垃圾收集器,当它看到一个准备收集的对象时,可能会或可能不会唤醒并完成其工作.Java中的GC通常是不值得信任的.
第二个答案:有时是,有时没有,但不值得冒险.来自Elliote Rusty Harold的Java IO:
例如,并非所有流都需要闭合 - 字节阵列输出流不需要关闭.但是,与文件和网络连接关联的流应始终在完成后关闭.例如,如果您打开文件进行写入而忽略了在您通过时关闭它,则可能会阻止其他进程读取或写入该文件.
根据Harold的说法,输入或输出流也是如此.有一些例外(他注意到System.in),但一般来说,如果你在完成后没有关闭文件流,你就冒了风险.并在finally块中关闭它们,以确保即使抛出异常也会关闭它们.
我曾经假设流最终会通过垃圾收集自动关闭,但轶事证据表明无法手动关闭它们会导致资源泄漏.你会想做这样的事情:
InputStream stream = null; try { stream = new FileInputStream("bar.txt"); Properties p = new Properties(); p.load(stream); } catch(Exception e) { // error handling } finally { closeQuietly(stream); }
closeQuietly()
是IOUtils
Apache的commons-io库中的一种方法.
不,Java中没有析构函数.可能存在对该对象的其他引用,即使在对该对象的一个特定引用超出范围(或被修改)之后也是如此.如果该对象不再可达,则该流可能在稍后的某个时间调用其终结器,这将关闭该流.
编辑:这Properties.load
在它关闭传递给它的流是特殊的.Properties.loadFromXML
是我似乎在大约五年前考虑过的特殊方法.(API doc应该先说而不是之后.)谢谢@tzimnoch.