2013-02-15 94 views
12

我有一個有很多最終成員的類,它們可以使用兩個構造函數之一進行實例化。構造函數共享一些代碼,存儲在第三個構造函數中。在Java中初始化最終字段

// SubTypeOne and SubTypeTwo both extend SuperType 

public class MyClass { 
    private final SomeType one; 
    private final SuperType two; 


    private MyClass(SomeType commonArg) { 
     one = commonArg; 
    } 

    public MyClass(SomeType commonArg, int intIn) { 
     this(commonArg); 

     two = new SubTypeOne(intIn); 
    } 

    public MyClass(SomeType commonArg, String stringIn) { 
     this(commonArg); 

     two = new SubTypeTwo(stringIn); 
    } 

的問題是,這段代碼不能編譯:Variable 'two' might not have been initialized.可能有人可能來自內部MyClass的調用第一個構造函數,然後將新的對象就沒有「二」中設置。

那麼在這種情況下,在構造函數之間共享代碼的首選方法是什麼?通常我會使用一個輔助方法,但共享代碼必須能夠設置最終變量,這隻能從構造函數完成。

+3

很難按照目前的理解你的問題,你有兩個相同的* *構造函數(參數相同,相同體)。你能解決它更具代表性嗎? – 2013-02-15 22:58:52

+2

在第一個構造函數中,兩個未初始化。 – 2013-02-15 22:59:39

+5

@Jon Skeet - 再看看,參數類型是不同的。 – 2013-02-15 23:01:02

回答

16

這個怎麼樣? (更新了更改的問題)

public class MyClass { 

    private final SomeType one; 
    private final SuperType two; 

    public MyClass (SomeType commonArg, int intIn) { 
     this(commonArg, new SubTypeOne(intIn)); 
    } 

    public MyClass (SomeType commonArg, String stringIn) { 
     this(commonArg, new SubTypeTwo(stringIn)); 
    } 

    private MyClass (SomeType commonArg, SuperType twoIn) { 
     one = commonArg; 
     two = twoIn; 
    } 
} 
+0

啊,那是我的錯。我把我的例子弄亂了一點;看看我現在寫的方式。然而,你給了我這樣一個想法:將兩個構造函數合併成一個需要SuperType的構造函數,並在調用之前調用者實際構造SuperType對象。我更喜歡在呼叫發生的地方沒有SuperType,但這是我能想到的最好的。 – 2013-02-15 23:53:15

+0

可以理解。這個怎麼樣?它避免了允許「SuperType」的任何子類,避免重複,並總是分配給兩個變量。注意,爲了避免含糊不清,在'null'上進行強制轉換。 https://gist.github.com/stickyd/4965120 – 2013-02-16 02:00:32

2

所有你需要做的就是確保「two」被初始化。在第一個構造函數,只需添加:

two = null; 

,除非是你想給它,只有第一個構造函數調用該事件的其他值。

+2

但是'two'是最終的。 – 2013-02-15 23:48:58

+0

你可以初始化一個最終變量爲null。它只需要被初始化爲* something *。如果你想要兩個非空值,那麼你必須調用其他構造函數之一。它與Sticky的答案有着相同的最終結果。 – Halogen 2013-02-16 00:06:07

+1

但問題是,如果我在第一個構造函數中將'two'設置爲null,那麼我無法在其他構造函數中設置它的實際值,因爲它已被設置。 – 2013-02-18 04:40:56

1

,因爲如果你曾打電話MyClass(SomeType oneIn)two未初始化你得到這個錯誤。

3

您需要確保在每個構造函數中初始化所有最終變量。我會做的是有一個構造函數初始化所有變量,並具有所有其他構造函數調用,如果有一個字段沒有賦值,則傳入null或某個默認值。

例子:

public class MyClass { 
    private final SomeType one; 
    private final SuperType two; 

    //constructor that initializes all variables 
    public MyClas(SomeType _one, SuperType _two) { 
     one = _one; 
     two = _two; 
    } 

    private MyClass(SomeType _one) { 
     this(_one, null); 
    } 

    public MyClass(SomeType _one, SubTypeOne _two) { 
     this(_one, _two); 
    } 

    public MyClass(SomeType _one, SubTypeTwo _two) { 
     this(_one, _two); 
    } 
}