定稿

Java 对象可以声明 finalize 方法。在 Java 释放对象的内存之前调用此方法。它通常如下所示:

public class MyClass {
  
    //Methods for the class

    @Override
    protected void finalize() throws Throwable {
        // Cleanup code
    }
}

但是,Java 终结的行为有一些重要的警告。

  • Java 不保证何时调用 finalize() 方法。
  • Java 甚至不保证在运行应用程序的生命周期中某个时候会调用 finalize() 方法。
  • 唯一可以保证的是,在删除对象之前将调用该方法…如果删除该对象。

上面的警告意味着依靠 finalize 方法执行必须及时执行的清理(或其他)操作是一个坏主意。过度依赖最终确定可能导致存储泄漏,内存泄漏和其他问题。

简而言之,极少数情况下,最终确定是一个很好的解决方案。

终结者只运行一次

通常,对象在完成后将被删除。但是,这并不是一直发生的。考虑以下示例 1

public class CaptainJack {
    public static CaptainJack notDeadYet = null;

    protected void finalize() {
        // Resurrection!
        notDeadYet = this;
    }
}

CaptainJack 的实例变得无法访问且垃圾收集器试图回收它时,finalize() 方法将为 notDeadYet 变量分配对实例的引用。这将使实例再次可达,垃圾收集器不会删除它。

问题:杰克船长不朽吗?

答:没有。

问题是 JVM 只会在其生命周期内对对象运行一次终结器。如果将 null 分配给 notDeadYet,导致再次无法访问已恢复的实例,则垃圾收集器将不会在该对象上调用 finalize()

1 - 请参阅 https://en.wikipedia.org/wiki/Jack_Harkness