2013-07-24 118 views
4

當我定義的Java類:如何初始化實例成員?

class A { 
    private String str = "init method 1"; 

    public A() { 
     str = "init method 2"; 
    } 
} 

我既可以初始化str,當把它定義或init它的構造函數。我的問題是兩種方法有什麼區別?哪種方法是首選?

+0

你在談論實例成員(類成員將是'靜態')。請注意,您的問題沒有單一的正確答案,所以答案將基於意見。 –

+1

另外檢查這個問題:http://stackoverflow.com/questions/3918578/should-i-initialize-variable-within-constructor-or-outside-constructor – Yuri

回答

4

初始化塊值在構造函數分配給它們之前分配。

因此,值init member 1將首先分配,然後init member 2將被分配。

考慮從theJavaGeek

class InitBlocksDemo { 

    private String name ; 

    InitBlocksDemo(int x) { 
     System.out.println("In 1 argument constructor, name = " + this.name); 
    } 

    InitBlocksDemo() { 
     name = "prasad"; 
     System.out.println("In no argument constructor, name = " + this.name); 

    } 

    /* First static initialization block */ 
    static { 
     System.out.println("In first static init block "); 
    } 

    /* First instance initialization block */ 
    { 
     System.out.println("In first instance init block, name = " + this.name); 
    } 

    /* Second instance initialization block */ 
    { 
     System.out.println("In second instance init block, name = " + this.name); 
    } 

    /* Second static initialization block */ 
    static { 
     System.out.println("In second static int block "); 
    } 

    public static void main(String args[]) { 
     new InitBlocksDemo(); 
     new InitBlocksDemo(); 
     new InitBlocksDemo(7); 
    } 

} 

此輸出這個例子中,如下

In first static init block 
In second static int block 
In first instance init block, name = null 
In second instance init block, name = null 
In no argument constructor, name = prasad 
In first instance init block, name = null 
In second instance init block, name = null 
In no argument constructor, name = prasad 
In first instance init block, name = null 
In second instance init block, name = null 
In 1 argument constructor, name = null 

程序流動。

  • 當程序開始執行時,類InitBlocksDemo被加載到JVM中。
  • 靜態初始化塊按照它們在程序中出現的順序加載時運行。
  • 現在執行靜態塊時,遇到main方法。
  • 語句new InitBlocksDemo();導致無參數構造函數被調用。
  • 因爲有一個默認調用super無參數的構造函數,就進入超類即Object
  • ,它已經完成後,再控制回來我們班,並開始給予默認值實例變量。在這種情況下,變量名將被賦值爲null
  • 現在實例塊將按它們在程序中出現的順序執行。我們還沒有重新賦值給變量名,所以它會打印null
  • 執行實例塊後,控制權轉到構造函數。這裏name =「prasad」;將重新分配一個新值,因此「prasad」將打印在無參數構造函數中
  • 9.語句new InitBlocksDemo(7);導致調用單參數構造函數。其餘的過程是相同的。唯一的區別是名稱不重新分配一個新的值,因此它會打印null
3

不同之處在於分配發生時。

System.out.println(str); 

,你會看到你分配在構造函數中較新的一個以前的老值有: 字段構造函數運行之前,所以如果你加入這行到你的構造函數分配的常量值。

除了那個以外,沒有什麼區別,而且使用的主要是個人偏好。

個人anythiong我可以直接指定爲字段聲明的一部分 - 這就是我所做的。

3

他們之間沒有什麼區別,編譯器副本初始化塊建設者

如果,反編譯生成的類文件的類

class A { 
    private String str1 = "init method 1"; 

    private String str2; 

    public A() { 
     str2 = "init method 2"; 
    } 

    public A(String str2) { 
     str2 = str2; 
    } 
} 

你可以找到

class A 
{ 

    private String str1; 
    private String str2; 

    public A() 
    { 
     str1 = "init method 1"; 
     str2 = "init method 2"; 
    } 

    public A(String str2) 
    { 
     str1 = "init method 1"; 
     str2 = str2; 
    } 
} 
1

在我的個人經驗,它關於對象初始化的昂貴程度或詳細程度。其次,你也可以把它看成是懶惰創造vs積極創造。如果只涉及構造函數,我通常會在實例變量級別創建對象。如果還有其他調用來初始化成員,那麼調用肯定會被移到構造函數或需要初始化的方法中。

這就是爲什麼使用工廠方法模式來委託實際的對象創建到另一個類。