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?


person sangfroid    schedule 15.12.2010    source источник


Ответы (5)


Да, они инициализируются в том порядке, в котором они появляются в источнике. Вы можете прочитать все кровавые подробности в Спецификация языка Java, §12.4.2. См. шаг 9, который гласит:

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

person Laurence Gonsalves    schedule 15.12.2010


если есть подкласс и суперкласс.

  1. EX: «A»: суперкласс «B»: подкласс, который расширяет суперкласс «A»
  2. когда загружается класс B, тогда также загружается класс A
  3. все статические переменные получают память со значением по умолчанию из классов «A» и «B»
  4. затем статические члены (статическая переменная, статический блок) выполняются в порядке сверху вниз класса «A», а затем класса «B» в том порядке, в котором они объявлены. наконец, основной метод выполняется из подкласса автоматически.
person Biswajit Sahoo    schedule 01.04.2015

На самом деле не отвечая на вопрос, но задавая больше здесь -). Только что наткнулся на интересный пример со статическим порядком инициализации полей. Вот пример:

   public class Foo {

    private static final Long result = method1();

    private static String string = "something";

    private static Long method1() {
        if (string == null) {
            throw new IllegalStateException("BOOM");
        }
        return 1L;
    }

    public static void main(String[] args) {
        System.out.println("here");
    }
}

Это создаст исключение IllegalStateException. Я понимаю, что последовательность здесь такова, что сначала мы оцениваем поле «результат», которое вызывает метод1 () и обходит инициализацию «строкового» значения. «строка» должна быть константой, но я забыл поставить модификатор «final», когда писал тесты. Но должны ли такие случаи обрабатываться во время выполнения? Значение, когда мы вызываем «if (string == null)», должна ли JRE быть достаточно умной, чтобы проверить, что «строка» не была инициализирована, и инициализировать ее?

person Alexey Pismenskiy    schedule 26.10.2018

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

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);
   } 
}
person Siddhant Swami    schedule 13.09.2016