在重写的finalize()方法中关闭类IO资源

时间:2012-10-18 15:40:13

标签: java garbage-collection

如果我有一个使用IO资源的类,例如磁盘平面文件,数据库或其他形式的外部资源,那么在重写的finalize()方法中关闭这些流/连接的优缺点是什么?由GC运行?我虽然这可以利用现有的JVM GC,并减少依赖客户端调用类似closeResources()之类的类方法以及编写类似意大利面的try-catches(嵌套try-catches和ifs)的风险我最不喜欢的编程结构。)

作为一个具体的例子,我有一个简单的文件阅读包装器。该类由String filePath构造,它将文件读入List<String[]>。我不想在多个地方关闭BufferedReader,如果打开文件(catch子句)时出现问题,请关闭它,如果文件读得正常则关闭它。我想放它在一个地方,并确保它始终关闭,无论物体何时获得GC。

这种方法是一种很好的做法,还是我试图在Java的范围内为自己提供太高的便利?

3 个答案:

答案 0 :(得分:2)

这不是一个好主意,因为无法保证调用finalize()方法。

当您的代码完成后,关闭资源会更容易也更好。

如果您不喜欢编写嵌套的try-finally块来正确关闭资源,请使用类似commons-io's IOUtils的内容来静默关闭资源(或编写您自己的简单util方法以静默关闭它们) :

InputStream stream = ...;
try {
    ...
}
finally {
    IOUtils.closeQuietly(stream);
}

答案 1 :(得分:1)

当IO资源是实例变量时,您应该使用finalize()方法关闭它。

为什么?

  1. 因为它是一个实例变量,所以你需要它处于打开状态,因为某些方法会重复使用它。

  2. 如果您使用除finalize之外的方法关闭它,那么您正在创建temporal coupling,这意味着类用户需要知道他必须以某个时间顺序调用某些方法,即A之前的A等。

  3. 编辑:

    Java文档指出垃圾收集器不能保证在任何特定时间运行,并且只要有任何引用,就不会运行finalize()宾语。如果引用仍然存在,那就是内存泄漏,编程错误。当资源不是方法的本地资源时,finalize()是最佳选择。如果资源是方法的本地资源,请在finally的{​​{1}}末尾关闭它。

答案 2 :(得分:0)

是的,最后阻止始终是释放连接,I / O Sream等资源的最佳方法。