Singleton через enum путь инициализируется ленивым?

18

Это очень распространенный одноэлементный код перечисления:

public enum enumClazz{
   INSTANCE
   enumClazz(){
     //do something
   }
}

и множество мест сказали, что это ленивая инициализация. Но я смущен после того, как прочитал главу 7 « Внутри виртуальной машины Java » - время жизни a Тип:

  

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

     
  • Создается новый экземпляр класса (в байт-кодах, выполнение новой инструкции. В качестве альтернативы, посредством неявного создания,   отражения, клонирования или десериализации.)
  •   
  • Вызов статического метода, объявленного классом (в байт-кодах, выполнение invokestatic инструкции)
  •   
  • Использование или назначение статического поля, объявленного классом или интерфейсом, за исключением статических полей, которые являются окончательными и инициализируются   выражение константы времени компиляции (в байт-кодах, выполнение   getstatic или putstatic)
  •   
  • Вызов некоторых отражающих методов в Java API, таких как методы класса Class или классы в java.lang.reflect   пакет
  •   
  • Инициализация подкласса класса (инициализация класса требует предварительной инициализации его суперкласса.)
  •   
  • Обозначение класса как исходного класса (с помощью метода main () & lt;) при запуске виртуальной машины Java
  •   

Третья точка с жирным стилем уточняет, что если поле static final , инициализация поля происходит во время компиляции. Аналогично, INSTANCE в enumClazz неявно равно public static final и соответствует третьей точке.

Может ли кто-то исправить меня, если мое понимание неверно?

    
задан vash_ace 27.05.2013 в 12:41
источник

2 ответа

25

enum полей экземпляра not "инициализируются выражением константы времени компиляции". Oни не может быть, потому что только String и примитивные типы возможные типы для выражения константы времени компиляции .

Это означает, что класс будет инициализирован, когда сначала будет вызван INSTANCE (что является точно желаемым эффектом).

Исключение в жирном тексте выше существует, поскольку эти константы ( static final , инициализированные с помощью выражения константы времени компиляции) будут эффективно включены во время компиляции:

class A {
  public static final String FOO = "foo";

  static {
    System.out.println("initializing A");
  }
}

class B {
  public static void main(String[] args) {
    System.out.println(A.FOO);
  }
}

Выполнение класса B в этом примере будет не инициализировать A (и будет not печатать "инициализацию A"). И если вы посмотрите на байт-код, сгенерированный для B , вы увидите строковый литерал со значением «foo» и no ссылку на класс A .

    
ответ дан Joachim Sauer 27.05.2013 в 12:45
источник
4
  

Третья точка с жирным стилем уточняет, что если поле является «статическим окончанием», то инициализация поля происходит в режиме согласования

Не совсем - он применяется только к « статическим полям, которые являются окончательными и инициализируются выражением константы времени компиляции ":

static final String = "abc"; //compile time constant
static final Object = new Object(); //initialised at runtime

В вашем случае синглтон будет инициализирован, когда загружается класс перечисления, т. е. первый раз, когда enumClazz ссылается на ваш код.

Таким образом, это эффективно лениво, если у вас нет инструкции где-то в вашем коде, например, например, что бы излишне инициализировать ваш синглтон как часть процесса загрузки класса:

Class<?> c = enumClazz.class;
    
ответ дан assylias 27.05.2013 в 12:46
источник
  • class Singleton {public static final instance = new Singleton (); ...} Итак, для универсального класса этот «экземпляр» инициализирован ленивым? –  vash_ace 27.05.2013 в 16:44
  • Да, это было бы лениво инициализировано таким же образом. –  assylias 27.05.2013 в 17:06
  • Все очищено. Огромное спасибо :) –  vash_ace 27.05.2013 в 17:09