Java: в каком порядке инициализируются статические конечные поля? - PullRequest
32 голосов
/ 15 декабря 2010

Хорошо, скажем, у меня есть класс, который выглядит так:

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?

Ответы [ 5 ]

50 голосов
/ 15 декабря 2010

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

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

3 голосов
/ 15 декабря 2010

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

В ряде случаев доступ к программным переменным (поля экземпляров объекта, статические поля класса и элементы массива) может бытькажется, чтобы выполнить в другом порядке, чем было указано в программе.

1 голос
/ 01 апреля 2015

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

  1. EX: «А»: супер класс «B»: подкласс, расширяющий суперкласс «A»
  2. когда класс B загружен, тогда класс A также загружается
  3. все статические переменные получают память со значением по умолчанию из классов 'A' и 'B'
  4. тогда статические члены (статическая переменная, статический блок) выполняются в порядке сверху вниз класса 'A' и затем класса 'B' в порядке, который они объявили. наконец, основной метод выполняется из подкласса автоматически.
0 голосов
/ 26 октября 2018

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

   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. Я понимаю, что последовательность здесь заключается в том, что сначала мы оцениваем поле «result», которое вызывает method1 () и обходит инициализацию значения «string». «string» должен быть константой, но я забыл поставить модификатор «final», когда писал тесты. Но должны ли такие случаи обрабатываться во время выполнения? То есть, когда мы вызываем «if (string == null)», должен ли JRE быть достаточно умным, чтобы проверить и убедиться, что «string» не была инициализирована и инициализировать ее?

0 голосов
/ 13 сентября 2016

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

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);
   } 
}
...