2011-01-13 68 views
5

我個人非常喜歡實例初始化器 - 我使用它們爲集合等事物分配默認值,所以在編寫構造函數時,我不必記住每次都爲它們分配相同的默認值。對我而言,這看起來很優雅 - 避免了NPE出現令人討厭的問題,避免了重複的代碼。私有方法看起來並不好,因爲a)它不能將值賦給final字段,b)它可能在代碼中的其他地方運行,c)仍然需要在每個構造函數的開始時顯式調用該方法。實例初始化器是否被認爲是壞風格?

但是,與他人談話的另一面是他們很混淆,一些讀代碼的人可能不明白他們做什麼或什麼時候被調用,因此他們可能會導致比他們解決更多的問題。

是否正確使用這些初始值設定項需要鼓勵或避免?或者它是「各自爲戰」的情況?

+3

沒有語言功能是「好」還是「壞」 - 所有事情都有一個真正閃耀的情形。我認爲更好的問題是「在什麼情況下要避免或使用實例初始化器?」 – templatetypedef 2011-01-13 01:45:47

+1

你幾乎總是希望集合類型的字段是'final',它解決了那些NPE問題。 – 2011-01-13 02:35:24

回答

3

這取決於,例如在你的代碼的Java的讀者知識水平,可以預計將有和方案是否切實可行。

替代品有:

  • 內嵌到每一個構造函數。如果有幾個構造函數,則違反了DRY。
  • 將所有構造函數委託給相同的構造函數,並將代碼放入該構造函數中。如果構造函數不平凡並且採用不同的參數,則可能需要編寫一個新的構造函數,該構造函數接收參數中所有字段的值。如果有許多字段,這可能會相當長(並且很難閱讀,因爲哪個值分配給哪個字段並不明顯)
  • 所有構造函數都調用init方法。無法以這種方式分配最終字段。應該可能防止該方法被覆蓋。可能要防止它被多次調用。

由於初始值設定項並不常見,所以只有在明確使用它們的優點時才應該使用它們。我最近使用的一個是:

private final Collator collator = Collator.getInstance(); 
{ 
    collator.setStrength(Collator.SECONDARY); 
} 

在一個類中有幾個構造函數具有相當不同的參數列表和六個其他字段。

0

您可以使用帶參數的構造函數,並且此構造函數調用私人setter。而不是實現一個用默認值調用該構造函數的默認構造函數。如果您想要將默認值分配給屬性,請在聲明中執行。

實例和靜態初始化器對初始化複雜數據結構(如矩陣或立方體)很有用。

順便說一句,最後的屬性大多數時候被稱爲常量。

1

我真的不使用他們,但一個情況下,我可以看到他們有用的是當你有多個構造函數,而不是自稱(這個(..)),需要一些常見的初始化邏輯共享,並且無需創建一個特定的私人方法。 哦,唯一的地方,我用實例初始化是在一個在線地圖,例如,如快速初始化:

Map<String,String> m = new HashMap<String,String>(){{ 
    put("a","b"); 
    put("c","b"); 
    put("d","b"); 
}}; 

可能是我們說的接口

interface A { 

    Map<String,String> PROPS = Collections.unmodifiableMap(new HashMap<String,String>(){{ 
     put("a","b"); 
     put("c","b"); 
     put("d","b"); 
    }}); 
} 

有用初始化地圖不過這樣做你最終的HashMap的annonymous子...

1

這是更好地超載的構造,並有儘可能多的構造變化,只要你喜歡。 Java的Arraylist就是最好的例子。它有兩個構造函數。一個將整數作爲參數,另一個作爲默認構造函數。如果你看一下默認的構造函數,它調用逸岸具有恆定值的單參數的構造函數10.

List<Object> x = new ArrayList<Object>(); //Creates with default capacity 10 
List<Object> y = new ArrayList<Object>(40); //Creates with the specified capacity 40 
1

我會留他們是首選。但基於其他的迴應,它似乎可能更「每個人都有自己的」。我喜歡他們,因爲它將相關信息保存在一起。而不是聲明一個值並在構造函數中設置它,你可以在一個地方完成所有的工作。

相關問題