2010-08-17 99 views
97

何時初始化靜態字段?如果我從來沒有實例化一個類,但我訪問一個靜態字段,所有的靜態塊和私有靜態方法用於實例化在那個時刻調用(按順序)的私有靜態字段?靜態類初始化何時發生?

如果我調用靜態方法怎麼辦?它是否也運行所有的靜態塊?方法之前?

+0

類似的靜態初始化塊:http://stackoverflow.com/questions/ 2007666/in-what-order-do-static-initializer-blocks-in-java-run – 2015-03-23 09:04:30

回答

138

類的靜態初始化通常第一次下列情形之一的前立即發生發生:

  • 的類的實例被創建,
  • 類的靜態方法被調用時,
  • 該類的靜態字段被分配,
  • 使用非恆定靜態字段或
  • 對於頂級類,詞類嵌套在類中的斷言語句是執行。

請參閱JLS 12.4.1

也可以強制類進行初始化(如果尚未初始化)使用Class.forName(fqn, true, classLoader)或短形式Class.forName(fqn)

+0

非常感謝您的額外信息。 – 2010-08-17 04:54:35

+5

用於給出JLS引用的+1 – Moshe 2013-04-03 19:50:49

+4

還要注意,較短形式的'Class.forName(className)'也強制初始化,因爲它等同於'Class.forName(className,true,currentLoader)'。 – user113215 2013-04-17 15:30:05

1

是的,所有靜態初始值設定項都是在首次訪問類之前運行的。如果是其他方式,我會稱之爲錯誤。

+0

有許多方法可以在不初始化的情況下引用某個類。 – 2017-05-23 00:56:56

11

靜態字段在類加載(加載,鏈接和初始化)的initialization「階段」中進行初始化,該階段包括靜態初始化程序及其靜態字段的初始化。靜態初始化器按照類中定義的文本順序執行。

考慮例如:

public class Test { 

    static String sayHello() { 
     return a; 
    } 

    static String b = sayHello(); // a static method is called to assign value to b. 
           // but its a has not been initialized yet. 

    static String a = "hello"; 

    static String c = sayHello(); // assignes "hello" to variable c 

    public static void main(String[] arg) throws Throwable { 
     System.out.println(Test.b); // prints null 
     System.out.println(Test.sayHello()); // prints "hello" 
    } 
} 

的Test.b打印null因爲當sayHello靜態範圍被稱爲,靜態變量a未初始化。

+6

嚴格來說,初始化不是類加載的「階段」。事實上,某些類可能會被加載,但如果應用程序沒有真正使用它們,則從未初始化。 – 2010-08-17 04:51:52

+0

@Stephen C你是對的,我用它缺乏一個更好的術語,也許我會引用它。 – naikus 2010-08-17 05:09:25

+0

@StephenC這是否意味着類加載發生時,它將內存分配給靜態變量(&方法),但這些靜態變量沒有使用代碼中提供的值進行初始化? ,因爲這裏看起來像b-> sayHello() - > a,'a'在內存中,但它的值尚未分配。 – 2018-02-06 07:36:38