Вопрос-ответ

When does static initialization happen?

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

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

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

Переведено автоматически
Ответ 1

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


  • создан экземпляр класса,

  • вызывается статический метод класса,

  • назначается статическое поле класса,

  • используется непостоянное статическое поле или

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

Смотрите JLS 12.4.1.

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



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


Смотрите выше.


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


Как часть статической инициализации класса; см. Выше.


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


Да. (По модулю ничто не происходит по-настоящему мгновенно.)


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


Да и да.


Обратите внимание, что можно создать код, в котором вы можете наблюдать инициализированное по умолчанию значение статического поля.


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

Ответ 2

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

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

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

Ответ 3

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

java