Когда инициализируются статические поля? Если я никогда не создаю экземпляр класса, но получаю доступ к статическому полю, вызываются ли (по порядку) в этот момент ВСЕ статические блоки и частные статические методы, используемые для создания экземпляра частных статических полей?
Что, если я вызову статический метод? Он также запускает все статические блоки? Перед методом?
Переведено автоматически
Ответ 1
Статическая инициализация класса обычно происходит непосредственно перед первым возникновением одного из следующих событий:
создан экземпляр класса,
вызывается статический метод класса,
назначается статическое поле класса,
используется непостоянное статическое поле или
для класса верхнего уровня выполняется оператор assert, лексически вложенный в класс1.
Когда происходит статическая инициализация класса?
Смотрите выше.
Когда инициализируются статические поля?
Как часть статической инициализации класса; см. Выше.
Если я никогда не создаю экземпляр класса, но получаю доступ к статическому полю, вызываются ли (по порядку) в этот момент ВСЕ статические блоки и частные статические методы, используемые для создания экземпляра частных статических полей?
Да. (По модулю ничто не происходит по-настоящему мгновенно.)
Что, если я вызову статический метод? Он также запускает все статические блоки? Перед методом?
Да и да.
Обратите внимание, что можно создать код, в котором вы можете наблюдать инициализированное по умолчанию значение статического поля.
1 - Последний маркерный пункт присутствовал в JLS для Java с 6 по Java 8, но, по-видимому, это была ошибка в спецификации. Это было окончательно исправлено в Java 9 JLS: см. Исходный код.
Ответ 2
Статические поля инициализируются во время "фазы" инициализации загрузки класса (связывание и инициализация), которая включает статические инициализаторы и инициализации его статических полей. Статические инициализаторы выполняются в текстовом порядке, как определено в классе.
Рассмотрим пример:
publicclassTest {
static String sayHello() { return a; }
staticStringb= sayHello(); // a static method is called to assign value to b. // but its a has not been initialized yet.
staticStringa="hello";
staticStringc= sayHello(); // assignes "hello" to variable c
publicstaticvoidmain(String[] arg)throws Throwable { System.out.println(Test.b); // prints null System.out.println(Test.sayHello()); // prints "hello" } }
Выводится Test.b, null потому что, когда sayHello была вызвана в статической области видимости, статическая переменная a не была инициализирована.
Ответ 3
Да, все статические инициализаторы запускаются перед первым обращением к классу. Если бы это было по-другому, я бы назвал это ошибкой.