是否可以在构造函数引发异常后调用 finalize?

2022-09-02 21:29:21

是否有任何关于是否使用对象的构造函数进行清理的详细信息,如果该对象的构造函数是异常的。finalize()

众所周知,当调用此方法时,定义不清。根据手册:

Java 编程语言不保证哪个线程将调用任何给定对象的 finalize 方法。但是,可以保证,在调用 finalize 时,调用 finalize 的线程不会持有任何用户可见的同步锁。如果 finalize 方法引发未捕获的异常,则忽略该异常并终止该对象的终结。

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29

我无法以这种方式触发finize方法。有谁知道它是否被限制不被调用,或者在某些情况下是否在构造函数未能初始化对象后被调用(这是一个例外)。

我问这个是因为我有一个对象,不能清理两次。我试图了解在抛出异常之前清理是否安全,或者我是否必须留下一个标记才能有效地跳过并且不执行任何操作。finalize()


答案 1

我的测试表明它可以

public class Test1 {

    Test1() {
        throw new RuntimeException();
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalized");
    }

    public static void main(String[] args) throws Exception {
        try {
            new Test1();
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        System.gc();
        Thread.sleep(1000);
    }
}

指纹

java.lang.RuntimeException
    at test.Test1.<init>(Test1.java:13)
    at test.Test1.main(Test1.java:24)
finalized

它位于 Java HostSpot Client VM 1.7.0_03 上


答案 2

根据第12.6.1节。实施 JLS 的最终确定:

对象 o 在其构造函数调用了 Object on o 的构造函数并且该调用已成功完成(即,未引发异常)之前,该对象 o 不可最终确定。

如果构造函数在 Object 构造函数完成后引发异常,则对象应该是可最终确定的,因此仍可调用。finalize()

在 12.5 节中有一个很好的单步执行对象构造的示例。创建新的类实例,该实例准确显示何时调用 Object 构造函数。