Java: в каком порядке инициализируются статические конечные поля?
Хорошо, скажем, у меня есть класс, который выглядит так:
public class SignupServlet extends HttpServlet {
private static final Logger SERVLET_LOGGER=COMPANYLog.open(SignupServlet.class);
private static final ExceptionMessageHandler handler = new ExceptionMessageHandler();
private static final SignupServletObservableAgent signupObservableAgent =
new SignupServletObservableAgent(null, SERVLET_LOGGER);
}
Можно ли рассчитывать на загрузчик классов для инициализации этих полей в порядке, чтобы я мог полагаться на SERVLET_LOGGER для создания экземпляра перед signupObservableAgent?
Ответы
Ответ 1
Да, они инициализируются в том порядке, в котором они появляются в источнике. Вы можете прочитать все детали gory в Спецификация языка Java, §12.4.2. См. Шаг 9, который гласит:
... выполняет либо инициализаторы переменной класса, либо статические инициализаторы класса, либо инициализаторы поля интерфейса, в текстовом порядке, как если бы они были одним блоком, за исключением того, что конечные переменные класса и поля интерфейсов, значения которых константы компиляции - сначала инициализируются...
Ответ 2
Я думаю, что инициализация статических полей может быть переупорядочена. По крайней мере, так я понимаю спецификацию JMM
Существует ряд случаев, когда доступ к программным переменным (поля экземпляра объекта, статические поля класса и элементы массива) может казаться выполненным в другом порядке, чем указано программой.
Ответ 3
если существует подкласс и суперкласс.
- EX:
"A" : суперкласс
"B": подкласс, и он расширяет суперкласс "A"
- когда класс B загружается, тогда класс A также загружает
- все статические переменные получают память со значением по умолчанию из классов "A" и "B"
- тогда статические члены (статическая переменная, статический блок) выполняются в верхнем и нижнем порядке класса "А", а затем "В", чтобы объявить их.
наконец, основной метод, выполняемый из подкласса автоматически.
Ответ 4
Это место, где вы можете использовать статический блок, который гарантировал бы последовательность выполнения.
public class SignupServlet extends HttpServlet {
private static final Logger SERVLET_LOGGER;
private static final ExceptionMessageHandler handler;
private static final SignupServletObservableAgent signupObservableAgent;
static {
SERVLET_LOGGER = COMPANYLog.open(SignupServlet.class);
handler = new ExceptionMessageHandler();
signupObservableAgent = new SignupServletObservableAgent(null, SERVLET_LOGGER);
}
}