2

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

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

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

4

3 回答 3

2

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

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

如果您讨厌编写嵌套的 try-finally 块来正确关闭资源,请使用commons-io 的 IOUtils之类的东西来静默关闭资源(或编写自己的简单 util 方法以静默关闭它们):

InputStream stream = ...;
try {
    ...
}
finally {
    IOUtils.closeQuietly(stream);
}
于 2012-10-18T15:45:22.507 回答
2

当 IO 资源是一个实例变量时,你应该在finalize()方法中关闭它。

为什么 ?

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

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

编辑:

Java 文档指出,垃圾收集器不能保证在任何特定时间finalize()运行,并且只要有对对象的任何引用就不会运行 。如果引用仍然存在,那就是内存泄漏、编程错误。finalize()当资源不是方法的本地资源时,这是最佳选择。如果资源是方法的本地资源,则finallytry/cath block.

于 2012-10-18T16:01:42.500 回答
0

是的,finally 块始终是释放连接、I/O Sreams 等资源的最佳方法。

于 2012-10-18T15:54:19.977 回答