OutputStream 对象(作为方法调用中的表达式创建,但未分配给变量)是否仍应关闭?
Should an OutputStream object (created as an expression in method call, but not assigned to a variable) still be closed?
我正在尝试匿名使用 FileOutputStream 来使用 java.util.Property 的存储方法存储 属性。
Properties p = new Properties();
. . .
p.store(new FileOutputStream("nameOfFile"), "Created by me.");
阅读 store 方法的 javadoc,它说在方法 returns 之后流将被刷新并保持打开状态。
我想知道流发生了什么。因为我已经匿名实例化它,所以我假设该对象将立即被垃圾收集(如果那是错误的,请纠正我)。但是,我被教导要在完成时关闭我的流。在这种情况下,我无法关闭流,因为我没有对象引用它。我是否需要担心流在这里保持打开状态,或者 Java 在这种情况下通过立即收集对象来适当地处理它?
那不是匿名对象(或者更确切地说是匿名 class)。这只是一个未分配的对象实例化。
创建它并将其传递给 store
后,就会有一个对它的引用,因此它不会被 GC。一旦 store
returns 该引用消失,但您仍应跟踪变量并在 store
returns 之后处理它。以相同的标准方式处理所有资源并在完成后调用 close
更安全,这有助于避免某些 finalize
方法调用 [=14= 时出现大量资源泄漏错误] ad other's don’t,并且还避免了由于非确定性 GC 引起的问题。
您还不知道未来版本的终结器实现可能会发生什么变化,因此始终调用 close
是最佳做法。
try-with-resources 块 (Java Tutorials > The try-with-resources statement) 非常适合:
Properties p = new Properties();
try (FileOutputStream stm = new FileOutputStream("nameOfFile"))
{
p.store(stm, "Created by me.");
} catch (IOException e) {
// TODO: handle this
}
当与任何(可能是多个)Autocloseable
一起使用时,该块将在最后调用 close
并很好地处理诸如 close
上的异常或正文中的异常之类的事情在 close
上也是如此。如果正文和 close
都抛出异常,则重新抛出正文异常并且 close
异常可通过 e.getSuppressed()
.
获得
如果您使用这些块之一,则不应自己调用 Autocloseable.close()
,因为该方法不是幂等的 - 调用它两次可能会在第二次产生副作用。如果你有一个 Closeable
那么你可以安全地多次调用它。来自文档:
Note that unlike the close method of Closeable, this close method is not required to be idempotent
在 Java 6 或更少版本中,您必须执行自己的异常处理语句,这很难,因为您必须处理您的主体和 close
都抛出异常的情况。
垃圾收集一般不包括打开的文件或流等资源,除非finalize
方法显式关闭对象的底层资源。
检查 finalize
的 FileOutputStream
代码,似乎可以确保调用 close
:
/**
* Cleans up the connection to the file, and ensures that the
* <code>close</code> method of this file output stream is
* called when there are no more references to this stream.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
/*
* Finalizer should not release the FileDescriptor if another
* stream is still using it. If the user directly invokes
* close() then the FileDescriptor is also released.
*/
runningFinalize.set(Boolean.TRUE);
try {
close();
} finally {
runningFinalize.set(Boolean.FALSE);
}
}
}
}
但是,始终 手动关闭资源或在 try-with-resources
语句中总是更好,因为并非所有流对象都可能在取消引用时关闭,即使他们完成了,也不能保证按照预期发生:
try(FileOutputStream outStream = new FileOutputStream("nameOfFile")) {
Properties p = new Properties();
. . .
p.store(outStream, "Created by me.");
}
创建对象...
FileOutputStream fos = new FileOutputStream("nameOfFile")
然后使用它...
p.store(fos, "Created by me.");
最后关闭它。
Properties.store() 命令不保留对流的引用,因此没有对它的引用,因此它将在方法 returns 之后进行 GC,因为这就是范围流范围。
我正在尝试匿名使用 FileOutputStream 来使用 java.util.Property 的存储方法存储 属性。
Properties p = new Properties();
. . .
p.store(new FileOutputStream("nameOfFile"), "Created by me.");
阅读 store 方法的 javadoc,它说在方法 returns 之后流将被刷新并保持打开状态。
我想知道流发生了什么。因为我已经匿名实例化它,所以我假设该对象将立即被垃圾收集(如果那是错误的,请纠正我)。但是,我被教导要在完成时关闭我的流。在这种情况下,我无法关闭流,因为我没有对象引用它。我是否需要担心流在这里保持打开状态,或者 Java 在这种情况下通过立即收集对象来适当地处理它?
那不是匿名对象(或者更确切地说是匿名 class)。这只是一个未分配的对象实例化。
创建它并将其传递给 store
后,就会有一个对它的引用,因此它不会被 GC。一旦 store
returns 该引用消失,但您仍应跟踪变量并在 store
returns 之后处理它。以相同的标准方式处理所有资源并在完成后调用 close
更安全,这有助于避免某些 finalize
方法调用 [=14= 时出现大量资源泄漏错误] ad other's don’t,并且还避免了由于非确定性 GC 引起的问题。
您还不知道未来版本的终结器实现可能会发生什么变化,因此始终调用 close
是最佳做法。
try-with-resources 块 (Java Tutorials > The try-with-resources statement) 非常适合:
Properties p = new Properties();
try (FileOutputStream stm = new FileOutputStream("nameOfFile"))
{
p.store(stm, "Created by me.");
} catch (IOException e) {
// TODO: handle this
}
当与任何(可能是多个)Autocloseable
一起使用时,该块将在最后调用 close
并很好地处理诸如 close
上的异常或正文中的异常之类的事情在 close
上也是如此。如果正文和 close
都抛出异常,则重新抛出正文异常并且 close
异常可通过 e.getSuppressed()
.
如果您使用这些块之一,则不应自己调用 Autocloseable.close()
,因为该方法不是幂等的 - 调用它两次可能会在第二次产生副作用。如果你有一个 Closeable
那么你可以安全地多次调用它。来自文档:
Note that unlike the close method of Closeable, this close method is not required to be idempotent
在 Java 6 或更少版本中,您必须执行自己的异常处理语句,这很难,因为您必须处理您的主体和 close
都抛出异常的情况。
垃圾收集一般不包括打开的文件或流等资源,除非finalize
方法显式关闭对象的底层资源。
检查 finalize
的 FileOutputStream
代码,似乎可以确保调用 close
:
/**
* Cleans up the connection to the file, and ensures that the
* <code>close</code> method of this file output stream is
* called when there are no more references to this stream.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
/*
* Finalizer should not release the FileDescriptor if another
* stream is still using it. If the user directly invokes
* close() then the FileDescriptor is also released.
*/
runningFinalize.set(Boolean.TRUE);
try {
close();
} finally {
runningFinalize.set(Boolean.FALSE);
}
}
}
}
但是,始终 手动关闭资源或在 try-with-resources
语句中总是更好,因为并非所有流对象都可能在取消引用时关闭,即使他们完成了,也不能保证按照预期发生:
try(FileOutputStream outStream = new FileOutputStream("nameOfFile")) {
Properties p = new Properties();
. . .
p.store(outStream, "Created by me.");
}
创建对象...
FileOutputStream fos = new FileOutputStream("nameOfFile")
然后使用它...
p.store(fos, "Created by me.");
最后关闭它。
Properties.store() 命令不保留对流的引用,因此没有对它的引用,因此它将在方法 returns 之后进行 GC,因为这就是范围流范围。