可以在构造函数抛出异常后调用finalize吗?

时间:2013-01-23 15:33:28

标签: java exception constructor

如果该对象的构造函数是异常,是否有使用finalize()清除对象的详细信息。

当调用此方法时,出了名的错误定义。根据手册:

  

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

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

我无法以这种方式触发finalize方法。有没有人知道它是不是被调用了,或者是否在某些情况下在构造函数初始化对象后调用(这是异常)。

我问这个是因为我有一个不能清理两次的物体。我试图了解在抛出异常之前清理是否安全,或者我是否必须为finalize()留下标记以有效地跳过并且什么都不做。

3 个答案:

答案 0 :(得分:11)

我的测试表明它可以

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 HotSpot Client VM 1.7.0_03

答案 1 :(得分:10)

根据JLS的12.6.1. Implementing Finalization部分:

  

对象o在其构造函数调用了o上的Object的构造函数并且该调用已成功完成(即不抛出异常)之前无法终结。

如果构造函数在对象构造函数完成后抛出异常,那么您的对象应该是可终结的,因此仍然可以调用finalize()

12.5. Creation of New Class Instances部分中逐步介绍对象构造,这是一个很好的例子,可以准确显示何时调用Object构造函数。

答案 2 :(得分:1)

更清楚地证明:

public class Test1 {

    public static class LifeBoat extends RuntimeException
    {
        private Test1 passenger;
        public Test1 getPassenger(){return passenger;}
        public LifeBoat(Test1 passenger){this.passenger=passenger;}
    }

    Test1() {
        super(); //once this is finished, there is an Object to GC per JLS 12.6.1. 
        throw new LifeBoat(this);
    }

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

    public static void main(String[] args) throws Exception {
        try {
            new Test1();
        } catch (LifeBoat e) {
            Test1 obj;
            obj=e.getPassenger();
            System.out.println(obj);
        }
        System.gc();
        Thread.sleep(1000);
    }
}

打印

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