Когда происходит инициализация статического класса? - PullRequest
107 голосов
/ 17 августа 2010

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

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

Ответы [ 3 ]

150 голосов
/ 17 августа 2010

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

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

См. JLS 12.4.1 .

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


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

13 голосов
/ 17 августа 2010

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

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

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

1 голос
/ 17 августа 2010

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

...