Java:关闭流后使引用为空
关闭流引用后将其设置为null是一种好的做法吗?这会以任何方式释放资源吗 例如:Java:关闭流后使引用为空,java,Java,关闭流引用后将其设置为null是一种好的做法吗?这会以任何方式释放资源吗 例如: BufferedReader input= new BufferedReader(new FileReader("myfile.txt")); // code input.close(); input = null; // possible more code 不,这是坏习惯。IMO,你甚至应该考虑制作变量最终< /代码> .< 应在标准acquire()中处理资源处理;尝试{use();}最后{relea
BufferedReader input= new BufferedReader(new FileReader("myfile.txt"));
// code
input.close();
input = null;
// possible more code
不,这是坏习惯。IMO,你甚至应该考虑制作变量<代码>最终< /代码> .< 应在标准
acquire()中处理资源处理;尝试{use();}最后{release();}
方式。在这种情况下:
final Reader rawIn = new FileReader("myfile.txt"); // Character encoding??
try {
BufferedReader in = new BufferedReader(rawIn);
// code
} finally {
rawIn.close();
}
实际上,这段代码将拾取任何设置为默认的字符编码。我建议显式使用特定的硬编码字符集或上面的参数
final InputStream rawIn = new FileInputStream("myfile.txt");
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(rawIn, "UTF-8")
);
// code
} finally {
rawIn.close();
}
您不应该在try块之外(在资源分配之前)创建包装流/读取器,因为它们可能会抛出。类似地,它们的关闭可能会抛出(这实际上是BufferedOutputStream
中的一个bug,它可能抛出flush
)。某些输入流可能有其他资源,因此您需要两个try{…finally{x.close();}
s
对于输出,您通常应该在正常事件过程中flush
。但在异常情况下通常不这样做。实际上close
通常执行flush
,因此您不应该在异常情况下关闭它们。如果装饰程序都flush
并且拥有资源,那么您将不得不露齿而笑。
在极少数情况下,清空是一个好主意。例如,如果一个变量是对一个大对象的唯一引用,并且您要创建一个新的大对象来分配给它,那么最好在分配新对象之前清除引用以允许回收旧对象。不需要。只需
input.close()
就足够了。记住在finally
块中执行此操作总是明智的。在调用close()之前,最好执行如下空检查
finally{
if(input!=null){
input.close();
}
}
除非您手动管理一个资源池(处理您自己的内存),否则没有必要为输入流设置空值。理想情况下,您使用的任何函数都很小,并且当对象超出范围时,对该对象的引用将消失,并将其标记为垃圾收集
我提到了资源池,就好像您天真地关闭了流而没有使对象为空一样,您可能会意外地保留一个您实际上并不需要的对象引用。这可能会使流对象本身符合垃圾收集的条件,但是
在大多数情况下,不管怎样,它都会超出范围
这样“释放”的内存量是微不足道的
在这种情况下,它是不需要的,垃圾收集器将收集它
但是分配null
并不总是一种不好的做法。请阅读中的第6项。不,它不是。close()
已经释放了资源。正常做法如下:
Resource resource = null;
try {
resource = new Resource();
// ...
} finally {
if (resource != null) try { resource.close(); } catch (ResourceException logOrIgnore) {}
}
其中,Resource
可以是您想要使用的任何外部资源,例如Java IO API的InputStream
,OutputStream
,Reader
和Writer
,但也可以是JDBC API的Connection
,Statement
和ResultSet
在设计良好的代码中,内存不是问题。如果代码离开了方法块,那么它已经符合GC的条件
您可以将close()
重构为如下实用程序方法:
public static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (ResourceException logOrIgnore) {
// Log it?
}
}
}
您可以按如下方式使用:
} finally {
close(resource);
}
提供了几种类似的实用方法。@Hei:欢迎使用SO。只是为了将来(如果您编辑此问题),您可以用四个空格缩进代码行,它们将显示在特殊的代码块中,这使它们更易于阅读。感谢您的评论,我将在以后的问题中对此进行研究。如果您在try块之前执行原始赋值,则不需要空值检查。只有当文件无法打开时,才会失败,在这种情况下无论如何都没有问题。好吧,不是马上。在后续收集中释放内存之前,它必须经过最终确定。或者,您可以将资源获取放在正确的位置w.r.t.try
。公平点,但有时您希望在相同的try
块中捕获、记录和/或重新显示异常,如果有必要,作为另一种例外。将船推出!使用两个try
块!!!然后使用Execute-Around成语。是的,我在这里见过(顺便说一句)。感谢您再次提醒:)(+1)。+1用于在流声明中使用final
。-1用于关闭内部(rawIn
)流。您应该始终关闭最派生的流。例如,在您的情况下,BufferedReader
的内部缓冲区中可能有一些数据。在
中调用关闭,将正确刷新此数据。调用关闭rawIn
将放弃此数据。感谢您的回答,并提到了一个取消为空的情况好主意。@Alexander是对的。BufferedReader
不过是一个很差的例子。不如用BufferedWriter
和小于8KB的内容来测试它。@BalusC你确实调用了flush
,不是吗?不,我希望close()。