什么时候进行静态类初始化?

Ton*_*y R 107 java static initialization

何时初始化静态字段?如果我从不实例化一个类,但是我访问一个静态字段,是否所有静态块和私有静态方法用于实例化那个时刻调用的私有静态字段(按顺序)?

如果我调用静态方法怎么办?它是否也运行所有静态块?方法之前?

Ste*_*n C 150

类的静态初始化通常在第一次发生以下事件之一之前发生:

  • 创建了一个类的实例,
  • 调用类的静态方法,
  • 分配了类的静态字段,
  • 使用非常量静态字段,或
  • 对于顶级类,在类中嵌套嵌套的断言语句执行1.

JLS 12.4.1.

也可以通过使用Class.forName(fqn, true, classLoader)或缩写来强制类初始化(如果尚未初始化)Class.forName(fqn)


1 - 最后一个要点出现在JLS for Java 6到Java 8中,但在规范中显然是一个错误.它最终在Java 9 JLS中得到了纠正:请参阅source.

  • 但是有一个共同的陷阱.原语和`String`s被替换而未被引用.如果引用`class Other {public static final int VAL = 10; 来自某些类`MyClass {private int = Other.VAL; }`,不会加载类`Other`.相反,编译器将在编译时简单地替换最终字段. (9认同)
  • @RafaelWinterhalter - 是的......这是**常量**静态字段情况. (6认同)
  • @RafaelWinterhalter,对于所有的“静态最终”原语或“字符串”变量而言,情况并非如此,仅适用于由常量表达式初始化的变量。 (2认同)
  • @RafaelWinterhalter,但是当字段不是“static”时,您需要对其实例的引用(即使之后使用常量值,编译器也会嵌入“null”检查),因此读取非“static”常量字段不会触发类初始化,但无论如何,在创建实例时初始化已经发生(如果不是更早的话) (2认同)

nai*_*kus 13

静态字段在类加载(加载,链接和初始化)的初始化 "阶段" 期间初始化,包括静态初始化器和其静态字段的初始化.静态初始值设定项按类中定义的文本顺序执行.

考虑这个例子:

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"
    }
}
Run Code Online (Sandbox Code Playgroud)

Test.b打印,null因为sayHello在静态范围内调用时,静态变量a未初始化.

  • 严格来说,初始化不是类加载的"阶段".实际上,如果应用程序实际上没有使用它们,可能会加载某些类*但从未初始化. (6认同)