Когда происходит инициализация статического класса?
Когда инициализируются статические поля? Если я никогда не создаю экземпляр класса, но получаю доступ к статическому полю, все ли статические блоки и частные статические методы используются для создания экземпляров частных статических полей, вызываемых (по порядку) в этот момент?
Что если я вызову статический метод? Он также запускает все статические блоки? Перед методом?
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
не был инициализирован.
Да, все статические инициализаторы запускаются перед первым доступом к классу. Если бы это было иначе, я бы назвал это ошибкой.