2013-01-23 154 views
13

是否存在任何有關是否使用finalize()清除對象的詳細信息,如果該對象的構造函數是異常。構造函數拋出異常後可以調用finalize嗎?

當這種方法被稱爲是臭名昭着的病態定義。根據手冊:

Java編程語言不保證哪個線程將 調用某個給定對象的finalize方法。但是,保證, 然而,當調用finalize時,調用finalize的線程將不會保留任何 用戶可見的同步鎖。如果finalize方法引發了 未捕獲的異常,則忽略 異常,並終止該對象的終止。

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

我已經無法觸發finalize方法以這種方式。有沒有人知道它是不是被調用的,或者在某些情況下在構造函數未能初始化對象之後調用它(這是一個例外)。

我問這是因爲我有一個對象,不能清理兩次。我試圖瞭解是否在拋出異常之前清理是否安全,或者如果我必須爲finalize()留下標記以有效地跳過並不執行任何操作。

+3

+1我懷疑這是你將需要檢查不同的JVM可能表現不同。 –

+0

使用'finalize'是邪惡的。 –

+1

@Peter JLS非常具體,一旦對象[base] Object的構造函數成功完成,對象就可以終結。 –

回答

10

我的測試表明,它可以

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

+0

這非常有幫助!你可以編輯你的答案,你試過這個JVM,我會接受它。非常感謝! –

+0

這是因爲隱含的super()沒有拋出異常。 –

7

根據JLS的第12.6.1. Implementing Finalization

對象o是直到它的構造函數爲o上的Object的構造函數調用並且該調用已成功完成(即沒有拋出異常),才能進行終結。

如果你的構造函數拋出的對象構造完成後異常,那麼你的對象應該是終結,所以finalize()仍可以調用。

在章節12.5. Creation of New Class Instances中介紹了一個很好的示例,介紹了對象構造,該示例準確顯示了何時調用Object構造函數。

+0

這意味着在類X中X(){super();}對象的super()調用已毫無例外地完成。 Object類具有膠水代碼,用於註冊垃圾收集的堆分配(由new分配)。 –

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) 
[email protected] 
finalized 
相關問題