Input/OutputStreams在销毁时是否关闭?

Cal*_*yth 12 java scope

Java中的InputStreams和OutputStreams是否在销毁时关闭()?我完全明白这可能是一个糟糕的形式(特别是在C和C++世界),但我很好奇.

另外,假设我有以下代码:

private void foo()
{
    final string file = "bar.txt";
    Properties p = new Properties();
    p.load( new FileInputStream(file) );
    //...
}
Run Code Online (Sandbox Code Playgroud)

无名的FileInputStream是否在p.load()之后超出范围,因此被销毁,有点像C++作用域规则?我尝试在Google上搜索java的匿名变量范围,但这并没有达到我认为的那样.

谢谢.

rtp*_*son 18

第一个答案:Java中没有"破坏"(在C++意义上).只有垃圾收集器,当它看到一个准备收集的对象时,可能会或可能不会唤醒并完成其工作.Java中的GC通常是不值得信任的.

第二个答案:有时是,有时没有,但不值得冒险.来自Elliote Rusty Harold的Java IO:

例如,并非所有流都需要闭合 - 字节阵列输出流不需要关闭.但是,与文件和网络连接关联的流应始终在完成后关闭.例如,如果您打开文件进行写入而忽略了在您通过时关闭它,则可能会阻止其他进程读取或写入该文件.

根据Harold的说法,输入或输出流也是如此.有一些例外(他注意到System.in),但一般来说,如果你在完成后没有关闭文件流,你就冒了风险.并在finally块中关闭它们,以确保即使抛出异常也会关闭它们.


Sin*_*hot 6

我曾经假设流最终会通过垃圾收集自动关闭,但轶事证据表明无法手动关闭它们会导致资源泄漏.你会想做这样的事情:

InputStream stream = null;

try {
  stream = new FileInputStream("bar.txt");
  Properties p = new Properties();
  p.load(stream);
}
catch(Exception e) {
  // error handling
}
finally {
  closeQuietly(stream);
}
Run Code Online (Sandbox Code Playgroud)

closeQuietly()IOUtilsApache的commons-io库中的一种方法.


Tom*_*ine 5

不,Java中没有析构函数.可能存在对该对象的其他引用,即使在对该对象的一个​​特定引用超出范围(或被修改)之后也是如此.如果该对象不再可达,则该流可能在稍后的某个时间调用其终结器,这将关闭该流.

Properties.load在它关闭传递给它的流是特殊的.编辑:这Properties.loadFromXML是我似乎在大约五年前考虑过的特殊方法.(API doc应该先说而不是之后.)谢谢@tzimnoch.

  • @ ChssPly76:是的,但是不能保证*无论何时,甚至是否会被调用终结者.没有. (5认同)