2010-08-17 83 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