美文网首页Effective Java Sencond Edition
Effective Java 第7条: 避免使用终结方法

Effective Java 第7条: 避免使用终结方法

作者: linyk3 | 来源:发表于2018-12-26 11:39 被阅读0次

终结方法(finalizer) 通常是不可预测的,也是很危险的,一般情况下是不必要的.

不要把终结方法当做是C++中的析构器的对应物:
C++ 需要析构器来与构造器对应,来回收对象所占的资源.
Java 中内存资源由垃圾收集器处理, 非内存资源由 try-finally 处理.

终结方法的缺点:

  • 不稳定: 不能保证会被及时执行
  • 可移植性低:及时执行终结算法是垃圾回收算法的一个主要功能, 不同的JVM的实现中会大相径庭.
  • 延迟终结过程: 一个类中的终结方法,可能会随意的延迟实例的回收过程.(终结方法线程的优先级低)
  • Java 语言规范不仅不保证终结方法会被及时执行,而且根本不保证他们会被执行.(不应该依赖终结方法来更新重要的持久状态) System.gc 和 System.runFinalization 两个方法仅仅是增加了终结方法被执行的机会,但并不保证终结方法一定会被执行.
  • 非常严重的性能损失: 创建和销毁普通对象: 5.6ns, 有终结方法的对象: 2400ns, 慢了大约340倍

如果 类的对象中封装的资源 (文件或者线程)确实需要终止,可以采用: 显式的终止方法 + try-finally

显式的终止方法,例如 InputStream, OutputString 和 java.sql.Connection 上的 close 方法.
在finally 里调用显式的终止方法,可以保证即使在使用对象时有异常抛出,该终止方法也会执行.

Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate();  // Explicit termination method
}

终结方法的两种合法用途:

  • 当对象的所有者忘记调用显式终止方法时,终结方法可以充当"安全网".(延迟释放好过因为代码bug造成永远不释放, 需要考虑这种额外的保护是否值得付出额外的代价)
  • 处理本地对等体(native peer),这不是普通的对象, 垃圾回收器不会知道它的存在,GC只会回收Java对等体.

注意:终结方法链不会被自动执行.如果类有终结方法,并且子类覆盖了终结方法, 子类的终结方法就必须手动调用超类的终结方法.

@override
protected void finalize() throws Throwable {
    try {
        ... // Finalize subclass state
    } finally {
        super.finalize();
        ... //
    }
}

如果子类覆盖了超类的终结方法,但是忘了调用超类的终结方法,那么超类的终结方法将永远不会被调用到.

总之,除非是作为安全网,或者为了终结非关键的本地资源,否则请不要使用终结方法.
如果使用了终结方法,记得super.finalize()

相关文章

网友评论

    本文标题:Effective Java 第7条: 避免使用终结方法

    本文链接:https://www.haomeiwen.com/subject/lpzclqtx.html