2012-05-16 111 views
68

任何人都可以解釋Java如何執行此代碼?我的意思是執行每個語句的順序。以靜態方式創建對象

public class Foo 
{ 
    boolean flag = sFlag; 
    static Foo foo = new Foo(); 
    static boolean sFlag = true; 

    public static void main(String[] args) 
    { 
     System.out.println(foo.flag); 
    } 
} 

OUTPUT:

false 
+4

我們是人,而不是計算機。我們是否應該嘗試使代碼更直接,而不是使用這些技巧或陷阱或其他什麼... –

+1

+1因爲這不是一個困難但很好的問題,我相信這將幫助其他人理解語言,特別是靜態修飾符更好。 @JonSkeet提供的非常有用的答案在一個有點重要 - 但經常被低估的話題上。 – jorey

+1

當人們使用'Foo'時,我不喜歡它。使用實際條款:/ – contactmatt

回答

104
  • 類初始化開始。最初,foo是零和sFlag是假
  • 第一個靜態變量初始化(foo)運行:
    • Foo一個新的實例被創建
    • flag實例變量初始化執行 - 當前sFlag是假的,所以的flag值爲false
  • 第二靜態變量初始值設定(sFlag)執行時,將該值設置爲true
  • 類初始化完成
  • main運行,打印出foo.flag,哪個是假

注意,如果sFlag被宣佈爲final它會作爲一個編譯時間常數進行處理,在這一點所有對它的引用基本上都會內聯到true,所以foo.flag也是如此。

+15

+1對於很好的解釋和'final':) –

+0

它與變量在類中定義的順序有關嗎?即如果'flag'是在'sflag'之後定義的? – Naveen

+0

@Naveen恕我直言,我不這麼認爲。靜態變量將首先被初始化。 –

12

foo類的靜態初始化期間被實例化,並SFlag的被初始化之前,和一個布爾值的默認值是假的。

  1. 類被裝載
  2. 美孚被初始化爲實例

    2.a的實例成員標誌被初始化爲SFlag的的值(false默認情況下)

  3. SFlag的初始化到true

請參考JLS §12.4瞭解更多詳情。

5

當加載課程時,sFlagfoo字段被初始化,但foo被初始化!
字段flagsFlag是布爾值,不能爲空,因此默認情況下爲false,而在foo初始化時仍然爲false。 flag = sFlag此之後flag是false.That是它

1

首先靜態字段應該運行,並在第一個內聯!所以在第4行和第5行將運行,所以foo首先被初始化,並且因爲我們知道布爾變量默認初始化爲false,所以一開始foo被初始化,flag的字段是sflag,這是false,然後sfalsg變成true,將不會改變標誌(沒有關係),然後在最後的主要運行和打印falg這是錯誤的! 我希望能有用!成功

2

初始化操作的一般順序是(類加載後和之前第一次使用):

  1. 靜態爲了它出現在代碼(類)的代碼塊,
  2. 對象代碼以便它出現在代碼中(初始化塊和賦值)。
  3. 構造

當然,我不指代的構造和功能體如上述一個碼塊

我不知道如何final static領域。它們看起來像遵循static字段的規則,並且在聲明之前無法引用它們,儘管先前的註釋表明它們在編譯步驟時已初始化。

Example.java:8: illegal forward reference 
     System.err.println("1st static block j=" + j); 

也許final static字段可以初始化並編譯成class文件,但是這不是一個一般的規則,他們仍然不能聲明之前引用:如果之前還有一個編譯錯誤被引用。

實施例的代碼來檢查初始化順序:

class Example {  

    final static int j = 5; 

    { 
     System.err.println("1st initializer j=" + j); 
    } 

    static { 
     System.err.println("1st static block j=" + j); 
    } 

    static { 
     System.err.println("2nd static block j=" + j); 
    } 

    final static java.math.BigInteger i = new java.math.BigInteger("1") {  
     { 
      System.err.println("final static anonymous class initializer"); 
     } 
    }; 

    Example() { 
     System.err.println("Constructor"); 
    } 

    static { 
     System.err.println("3nd static block j=" + j); 
    } 

    { 
     System.err.println("2nd initializer"); 
    } 

    public static void main(String[] args) { 
     System.err.println("The main beginning."); 
     Example ex = new Example(); 
     System.err.println("The main end."); 
    } 
} 

上面的代碼snipset打印:

1st static block j=5 
2nd static block j=5 
final static anonymous class initializer 
3nd static block j=5 
The main beginning. 
1st initializer j=5 
2nd initializer 
Constructor 
The main end. 
+0

JVM規範[詳細初始化過程](http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 0.2) –