2011-11-24 64 views
0

讓我們說我有下面的類Java實例成員初始化拋出異常

public class A { 
    private B b; 
} 

現在有一個工廠,用於創建B的實例,但創作者方法拋出一個異常

public class BCreatorFactory { 
    public static createB() throws SomeException { 
     // DO the intialization 
     // ... 
     return b; 
} 

如果我在聲明行中設置Ab,那麼我將無法處理異常

public class A { 
    private B b = BCreatorFactory.createB() // BAD -> no way of dealing with the exception 
} 

,如果我在構造函數中設置的Ab那麼我要麼有一個「半出爐的」實例或者我再次拋出一個異常,並強制調用代碼來處理不正確初始化實例

public class A { 
    private B b; 

    public A() { 
     try { 
     b = BCreatorFactory.createB(); 
     } 
     catch (SomeException se) { 
     // Do something, perhaps try to recover ? <- IMO also BAD 
     } 
    } 
} 

public class A { 
    private B b; 

    public A() throws SomeException { // BAD 
     b = BCreatorFactory.createB(); 
    } 
} 

我可以嘗試延遲初始化B的實例:

public class A { 
    private B b; 

    public B getB() throws SomeException { 
     if (b == null) { 
      b = BCreatorFactory.createB(); // BAD -> not thread safe -> can result in redundant createB() invocations 
     } 
     return b; 
    } 
} 

但我能想到使它線程安全的唯一方法是通過的已知的Java的JVM中內破雙重檢查鎖定

public class A { 
    private B b; 

    public B getB() throws SomeException { 
     if (b == null) { 
      synchronized(this) { 
       if (b == null) { 
        b = BCreatorFactory.createB(); // BAD -> not really thread safe -> broken 
       } 
      } 
     } 
     return b; 
    } 
} 

那麼,什麼,親愛的讀者病人,應該怎麼辦?

換句話說,什麼是初始化一個對象實例的最佳解決方案,該實例包含對創建可能會引發異常的對象的引用?

+4

我不清楚爲什麼你認爲讓A的構造函數拋出'SomeException'是一件壞事。 –

+0

爲什麼你認爲拋出B的異常是不好的? –

+0

當拋出異常時你期望發生什麼?如果不知道這個,很難知道該怎麼做。 –

回答

3

這是怎麼回事?

public class A { 
    private B b; 

    public A() throws SomeException { // BAD -- *no it's not* 
     b = BCreatorFactory.createB(); 
    } 
} 

構造函數拋出異常沒有任何問題。

0

構造函數拋出異常沒有任何問題。 Java框架中的許多類都會從構造函數中拋出異常。在構造函數中捕獲異常也很好,只要你有辦法自動處理和解決這種情況。在Java中檢查異常的目的是讓你不能忽略錯誤條件,你必須在某個地方處理它。

我拋出一個異常,並強制調用代碼來處理不正確初始化實例

調用代碼將不必處理不當初始化的情況下,它會自動進入到catch塊在那裏你應該做一些關於例外的事情,不管是拋出它,記錄它,失敗等等。