Есть ли какие-либо гарантии в JLS о порядке исполнения блоков статической инициализации?
-
26-09-2019 - |
Вопрос
Интересно, надежно ли использовать конструкцию, как:
private static final Map<String, String> engMessages;
private static final Map<String, String> rusMessages;
static {
engMessages = new HashMap<String, String> () {{
put ("msgname", "value");
}};
rusMessages = new HashMap<String, String> () {{
put ("msgname", "значение");
}};
}
private static Map<String, String> msgSource;
static {
msgSource = engMessages;
}
public static String msg (String msgName) {
return msgSource.get (msgName);
}
Есть ли возможность, что я получу NullPointerException
потому что msgSource
Блок инициализации будет выполнен до блока, который инициализируется engMessages
?
(о том, почему я не делаю msgSource
Инициализация в конце верхнего init. Блок: просто вопрос вкуса; Я сделаю это, если описанное конструкция ненадежна)
Решение
Да, статические блоки инициализатора гарантированно выполняются в текстовом порядке.
От JLS, Раздел 12.4.1:
Намерение заключается в том, что тип класса или интерфейса имеет набор инициализаторов, которые помещают его в постоянное состояние, и что это состояние является первым государством, которое наблюдается другими классами. Статические инициализаторы и анализа переменных классов выполняются в текстовом порядке, И не может ссылаться на переменные классов, объявленных в классе, декларации которых появляются текстовые после использования, даже если эти переменные классов находятся в области (§8.3.3). Это ограничение предназначено для обнаружения, при компиляции времени, большинству циркулярных или иным иным образом инициализированных инициализациях.
И из 12.4.2:
Затем выполните либо переменные классов инициализирующих переменных классов и статические инициализаторы класса или инициализаторы поля интерфейса, в текстовом порядке, Как будто они были одним блоком.
Лично, однако, я бы поставил все объявления переменной в начале, а затем единый статический блок инициализатора. Я считаю, что это намного легче следовать.