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

是否有任何关于是否使用finalize()清除对象的细节,如果该对象的构造函数是exception的话。

当调用这种方法时,出了名的不明确。 根据手册:

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

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

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

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

我的测试显示它可以

 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.(Test1.java:13) at test.Test1.main(Test1.java:24) finalized 

它位于Java HostSpot Client VM 1.7.0_03上

根据第12.6.1节。 实现 JLS的最终化:

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

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

在12.5节中,有一个很好的例子可以逐步完成对象构建。 创建新类实例 ,准确显示何时调用Object构造函数。

为了更清楚地certificate:

 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.(Test1.java:13) at test.Test1.main(Test1.java:24) test.Test1@6dc8f3cd finalized