Когда происходит инициализация статического класса?

Когда инициализируются статические поля? Если я никогда не создаю экземпляр класса, но получаю доступ к статическому полю, все ли статические блоки и частные статические методы используются для создания экземпляров частных статических полей, вызываемых (по порядку) в этот момент?

Что если я вызову статический метод? Он также запускает все статические блоки? Перед методом?

3 ответа

Решение

Статическая инициализация класса обычно происходит непосредственно перед первым случаем одного из следующих событий:

  • экземпляр класса создан,
  • вызывается статический метод класса,
  • статическое поле класса назначено,
  • используется непостоянное статическое поле, или
  • для класса верхнего уровня выполняется оператор assert, лексически вложенный в класс 1.

См. JLS 12.4.1.

Также можно принудительно инициализировать класс (если он еще не инициализирован), используя Class.forName(fqn, true, classLoader) или краткая форма Class.forName(fqn)


1 - последний пункт обозначен в JLS для Java 6 - Java 8, но, очевидно, это было ошибкой в ​​спецификации. Это было окончательно исправлено в Java 9 JLS: см. Источник.

Статические поля инициализируются во время "фазы" инициализации загрузки класса (загрузка, связывание и инициализация), которая включает в себя статические инициализаторы и инициализации его статических полей. Статические инициализаторы выполняются в текстовом порядке, как определено в классе.

Рассмотрим пример:

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 не был инициализирован.

Да, все статические инициализаторы запускаются перед первым доступом к классу. Если бы это было иначе, я бы назвал это ошибкой.

Другие вопросы по тегам