2015-05-09 33 views
3

瞭解有關加載類和調用靜態初始化遞歸初始化:當我訪問類字段

In what order do static initializer blocks

所以靜態初始化沒有得到所謂的,我只是想確認一下 -

public class OOMErrorB extends OOMErrorA { 
    public static int c = 10; 

    static { 
     System.out.println("Loading static B " + c); 
     System.out.println(OOMErrorA.a); 
    } 

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

父級是 -

public class OOMErrorA { 
    public static int a = 20; 

    static { 
     a = a+ OOMErrorB.c; 
     System.out.println("OOMErrorB.c " + OOMErrorB.c); 
     System.out.println("loading OOMErrorA.a " + a); 
    } 
} 

現在B的主要方法的輸出 -

**

OOMErrorB.c 0 
loading OOMErrorA.a 20 
Loading static B 10 
20 

**

我可以理解,第一它加載類A,因爲它的超類,並調用它的靜態初始化,

現在,因爲我正在訪問OOMErrorA的靜態塊中的OOMErrorB.c,它應該加載並調用OOMErrorB的靜態初始化程序。 所以,OOMErrorB.c應該是10而不是0。

我知道一類的加載和初始化什麼 -

1) Class and gets loaded and variables are initialized to default values like for int - 0, Object - null. 
2) Class field are initialized to specified values. 
3) Static block gets called . 

在我的計劃,我可以看到該類OOMErrorB得到加載(步驟1),但步驟2和步驟3未執行。

而根據鏈接上接受的答案,它應該調用OOMErrorB的靜態初始化器。

所以它應該最終在循環依賴?

回答

1

當訪問OOMErrorB.cOOMErrorB是不加載,因爲它已經是在被裝載時(當JVM最初加載它,以調用方法main)的過程。一旦一個類加載到JVM中,它就不會再被加載。因此,不會出現循環依賴:OOMErrorB的靜態成員c被提取,但此時尚未初始化。

您可以檢查this section from the Java language specification約類的初始化:

因爲Java編程語言是多線程的,一類或接口的初始化階段需要仔細同步,因爲一些其他線程試圖初始化同一類或接口與此同時。 也可能初始化一個類或接口可能被遞歸地請求作爲該類或接口的初始化的一部分;例如,類A中的變量初始值設定項可能會調用不相關的類B的方法,該方法可能又會調用類A的方法。Java虛擬機的實現負責處理同步和遞歸初始化,方法是使用遵循程序。

JVM有其正確的方式來鎖定類的初始化,以防止遞歸初始化。

+0

程序還沒有進入main方法,我們可以在那裏打印一個語句並看看。 –

+0

哦,我想我得到了這一點,所以JVM會這樣工作 - 1)它將加載類A(步驟1)2)然後它將加載類B(步驟1)3)它將調用類A的靜態4)它將調用B類的靜態。 –

+0

@AdonSmith你說得對。我的意思是在JVM調用它的'main'之前加載它。 – manouti