Есть ли какие-либо гарантии в JLS о порядке исполнения блоков статической инициализации?

StackOverflow https://stackoverflow.com/questions/3028219

  •  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:

Затем выполните либо переменные классов инициализирующих переменных классов и статические инициализаторы класса или инициализаторы поля интерфейса, в текстовом порядке, Как будто они были одним блоком.

Лично, однако, я бы поставил все объявления переменной в начале, а затем единый статический блок инициализатора. Я считаю, что это намного легче следовать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top