2015-02-03 5 views
4

У меня вопрос о Enum.Порядок выполнения Enum в java

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

public enum FontStyle { 
    NORMAL("This font has normal style."), 
    BOLD("This font has bold style."), 
    ITALIC("This font has italic style."), 
    UNDERLINE("This font has underline style."); 

    private String description; 

    FontStyle(String description) { 
     this.description = description; 
    } 
    public String getDescription() { 
     return this.description; 
    } 
} 

Интересно, когда объект создан Enum.

Enum выглядит как объект «static final», поскольку его значение никогда не изменится. Так что в этом случае он эффективен для инициализации только во время компиляции.

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

ответ

3

Да, перечисления являются статическими константами, но не являются константами времени компиляции. Точно так же, как и все другие пересылки классов загружаются при первом необходимости.Вы можете наблюдать это легко, если вы измените его конструктор немного

FontStyle(String description) { 
    System.out.println("creating instace of "+this);// add this 
    this.description = description; 
} 

и использовать простой тестовый код как

class Main { 
    public static void main(String[] Args) throws Exception { 
     System.out.println("before enum"); 
     FontStyle style1 = FontStyle.BOLD; 
     FontStyle style2 = FontStyle.ITALIC; 
    } 
} 

Если вы будете запускать main метод вы увидите выход

before enum 
creating instace of NORMAL 
creating instace of BOLD 
creating instace of ITALIC 
creating instace of UNDERLINE 

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

Вы также можете использовать

Class.forName("full.packag.name.of.FontStyle"); 

вызвать его груз, если он еще не был загружен.

+0

Спасибо за замечательный пример: D. Я был впечатлен. бб –

0

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

Очень важно, чтобы они создавались только один раз, так что сравнение идентичности объектов (==). Даже механизм сериализации объекта (de) должен был быть скорректирован для поддержки этого.

0

экземпляры перечислений создаются при класса связывания (разрешения), который является этапом, который приходит после загрузки класса, так же, как статических полей «нормального» класса.

Связывание классов происходит отдельно от загрузки класса. Поэтому, если вы динамически загружаете класс Enum с помощью загрузчика классов, константы будут создаваться только тогда, когда вы действительно пытаетесь получить доступ к одному из экземпляров, например, при использовании метода getEnumConstants() от Class.

Вот немного кода, чтобы проверить это утверждение:

File1: TestEnum.java

public enum TestEnum { 

    CONST1, CONST2, CONST3; 

    TestEnum() { 
     System.out.println("Initializing a constant"); 
    } 
} 

Файл2: Test.java

class Test 
{ 
    public static void main(String[] args) { 

     ClassLoader cl = ClassLoader.getSystemClassLoader(); 

     try { 
      Class<?> cls = cl.loadClass("TestEnum"); 
      System.out.println("I have just loaded TestEnum"); 
      Thread.sleep(3000); 
      System.out.println("About to access constants"); 
      cls.getEnumConstants(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 
} 

Выход :

 
I have just loaded TestEnum
... три секунды пауза ...
About to access constants 
Initializing a constant 
Initializing a constant 
Initializing a constant 

различие важно, если по какой-либо причине, вы не используете перечисление ясно (только со ссылкой на одного из его постоянных), но вместо этого полагаются на динамическую загрузку его ,

Примечание:

  • Использование Class.forName() оба нагрузки и связать класс, так что константы будут немедленно инстанцированы.
  • Достаточно получить доступ к одной константе для связывания всего класса, поэтому в это время будут созданы все константы.
+3

Ваш источник для этого утверждения? – EJP

+0

Здесь (не авторизовано, конечно) говорится, что они инициализируются при загрузке класса: http://stackoverflow.com/questions/18471653/how-java-ensures-only-one-instance-of-an-enum -per-jvm и http://stackoverflow.com/a/9408412/14955 и http://stackoverflow.com/a/18425768/14955 – Thilo

+0

@EJP и др. Я узнал об этом, отвечая на этот вопрос (http: //stackoverflow.com/q/28054222/4125191). Я протестировал, создав простую перечисление с печатью в его конструкторе, а затем загрузив его с помощью загрузчика классов. – RealSkeptic

Смежные вопросы