2010-10-06 3 views
8

Я просматривал документацию и исходный код, потому что я хотел быть уверенным, что values ​​() всегда будет возвращать массив в том порядке, в котором объявлены значения Enum. Оказывается, это не in the documentation, насколько я могу судить.Откуда Откуда: Enum.values ​​()?

Я проверил исходный код класса Enum и не повезло (there is a related, private "getValues" method).

Так что я предполагаю, что некоторые компилятор/интерпретатор-Foo уже происходит, чтобы создать класс, который расширяет Enum из заявления, как:

public static enum MyEnum 

Так значение() также статический переведены в жестко закодированный массив во время компиляции? Или это метод, называемый во время выполнения, и если да, то где он определен?

+0

Если вам это очень важно, это, вероятно, означает, что что-то сломается, если в объявлении перечисления вы будете перемещать вещи вокруг. Это очень хрупко. Поэтому я бы сказал, если вам все равно, у вас, вероятно, странный дизайн. Почему для вас важно, чтобы они были в порядке? –

+0

+1 Только для названия. – Zoe

+0

@Mark Peters - Потому что я использую перечисления для заказанных пунктов меню в нескольких местах. Конечно, я мог бы создать какую-то функцию упорядочения, которая вернула бы их в некотором порядке ... но почему? Он не сломается, если я их переведу, он просто изменит порядок, который будет представлен в приложении. – DougW

ответ

13

Метод values() является частью определения enum типа. Не следует путать с базовым классом Enum. Формальное определение находится в Section 8.9 of the JLS, которое указывает, что полученный заказ соответствует порядку, в котором они объявлены.

+0

+1 для спецификации! –

+0

Идеально, вот что я предполагал. Благодаря! – DougW

1

Указанная вами ссылка (где есть частный метод getValues) - от Apache Harmony (версия 6, которая является открытым исходным кодом Java SE). Они имеют различную реализацию для класса Enum Oracle (который не имеет частного метода getValues).

Oracle java (версия 1.6.0-21 на момент написания) имеет номер valueOf(Class<T> enumType, String name). Вот его реализация:

/** 
    * Returns the enum constant of the specified enum type with the 
    * specified name. The name must match exactly an identifier used 
    * to declare an enum constant in this type. (Extraneous whitespace 
    * characters are not permitted.) 
    * 
    * @param enumType the <tt>Class</tt> object of the enum type from which 
    *  to return a constant 
    * @param name the name of the constant to return 
    * @return the enum constant of the specified enum type with the 
    *  specified name 
    * @throws IllegalArgumentException if the specified enum type has 
    *   no constant with the specified name, or the specified 
    *   class object does not represent an enum type 
    * @throws NullPointerException if <tt>enumType</tt> or <tt>name</tt> 
    *   is null 
    * @since 1.5 
    */ 
    public static <T extends Enum<T>> T valueOf(Class<T> enumType, 
               String name) { 
     T result = enumType.enumConstantDirectory().get(name); 
     if (result != null) 
      return result; 
     if (name == null) 
      throw new NullPointerException("Name is null"); 
     throw new IllegalArgumentException(
      "No enum const " + enumType +"." + name); 
    } 

В сущности, это как Apache реализовали свою valueOf, который отличается.


Enum (или enum) имеет публичный статический метод, называемый values(), который возвращает значение константы перечисленного объявленную внутри enum. Это заполняется компилятором.

+2

* Shiver * Я все еще проползаю, увидев «класс Enum Oracle» или «Oracle Java». Заставляет меня думать, что вы говорите о JVM, которую они создали для использования в базах данных Oracle. –

+0

удерживайте имя, пока Oracle не сделает что-то важное для java. – irreputable

+0

LOL .... если вы не заметили парней, большинство сайтов 'sun.com' теперь' oracle.com'. Могу также принять тоже ... –

2

Как вы можете видеть из приведенного ниже байт-кода, полученного путем disassemlbing перечисления, метод values() на перечислениях просто возвращает копию массива private static, которая содержит всю объявленную константу перечисления. Этот массив ENUM$VALUES заполняется статическим блоком инициализации.

DaysOfTheWeek.java

public enum DaysOfTheWeek { 
    MONDAY, 
    TUESDAY, 
    WEDNESDAY, 
    THURSDAY, 
    FRIDAY, 
    SATURDAY, 
    SUNDAY 
} 

DaysOfTheWeek.java разобранном

После статического блока, байт-код инициализирует отмеченные 0-92 константы перечислений, байт-код отмеченные 94-139 ставит тех, константы в массиве и байт-код, отмеченный 140, присваивает массив статическому полю класса ENUM$VALUES. Код в методе values() просто создает копию массива, назначенного для поля ENUM$VALUES, вызывая на нем System.arraycopy и возвращает копию.

Compiled from "DaysOfTheWeek.java" 
public final class DaysOfTheWeek extends java.lang.Enum{ 
public static final DaysOfTheWeek MONDAY; 

public static final DaysOfTheWeek TUESDAY; 

public static final DaysOfTheWeek WEDNESDAY; 

public static final DaysOfTheWeek THURSDAY; 

public static final DaysOfTheWeek FRIDAY; 

public static final DaysOfTheWeek SATURDAY; 

public static final DaysOfTheWeek SUNDAY; 

static {}; 
    Code: 
    0: new #1; //class DaysOfTheWeek 
    3: dup 
    4: ldC#18; //String MONDAY 
    6: iconst_0 
    7: invokespecial #19; //Method "<init>":(Ljava/lang/String;I)V 
    10: putstatic #23; //Field MONDAY:LDaysOfTheWeek; 
    13: new #1; //class DaysOfTheWeek 
    16: dup 
    17: ldC#25; //String TUESDAY 
    19: iconst_1 
    20: invokespecial #19; //Method "<init>":(Ljava/lang/String;I)V 
    23: putstatic #26; //Field TUESDAY:LDaysOfTheWeek; 
    26: new #1; //class DaysOfTheWeek 
    29: dup 
    30: ldC#28; //String WEDNESDAY 
    32: iconst_2 
    33: invokespecial #19; //Method "<init>":(Ljava/lang/String;I)V 
    36: putstatic #29; //Field WEDNESDAY:LDaysOfTheWeek; 
    39: new #1; //class DaysOfTheWeek 
    42: dup 
    43: ldC#31; //String THURSDAY 
    45: iconst_3 
    46: invokespecial #19; //Method "<init>":(Ljava/lang/String;I)V 
    49: putstatic #32; //Field THURSDAY:LDaysOfTheWeek; 
    52: new #1; //class DaysOfTheWeek 
    55: dup 
    56: ldC#34; //String FRIDAY 
    58: iconst_4 
    59: invokespecial #19; //Method "<init>":(Ljava/lang/String;I)V 
    62: putstatic #35; //Field FRIDAY:LDaysOfTheWeek; 
    65: new #1; //class DaysOfTheWeek 
    68: dup 
    69: ldC#37; //String SATURDAY 
    71: iconst_5 
    72: invokespecial #19; //Method "<init>":(Ljava/lang/String;I)V 
    75: putstatic #38; //Field SATURDAY:LDaysOfTheWeek; 
    78: new #1; //class DaysOfTheWeek 
    81: dup 
    82: ldC#40; //String SUNDAY 
    84: bipush 6 
    86: invokespecial #19; //Method "<init>":(Ljava/lang/String;I)V 
    89: putstatic #41; //Field SUNDAY:LDaysOfTheWeek; 
    92: bipush 7 
    94: anewarray #1; //class DaysOfTheWeek 
    97: dup 
    98: iconst_0 
    99: getstatic #23; //Field MONDAY:LDaysOfTheWeek; 
    102: aastore 
    103: dup 
    104: iconst_1 
    105: getstatic #26; //Field TUESDAY:LDaysOfTheWeek; 
    108: aastore 
    109: dup 
    110: iconst_2 
    111: getstatic #29; //Field WEDNESDAY:LDaysOfTheWeek; 
    114: aastore 
    115: dup 
    116: iconst_3 
    117: getstatic #32; //Field THURSDAY:LDaysOfTheWeek; 
    120: aastore 
    121: dup 
    122: iconst_4 
    123: getstatic #35; //Field FRIDAY:LDaysOfTheWeek; 
    126: aastore 
    127: dup 
    128: iconst_5 
    129: getstatic #38; //Field SATURDAY:LDaysOfTheWeek; 
    132: aastore 
    133: dup 
    134: bipush 6 
    136: getstatic #41; //Field SUNDAY:LDaysOfTheWeek; 
    139: aastore 
    140: putstatic #43; //Field ENUM$VALUES:[LDaysOfTheWeek; 
    143: return 

public static DaysOfTheWeek[] values(); 
    Code: 
    0: getstatic #43; //Field ENUM$VALUES:[LDaysOfTheWeek; 
    3: dup 
    4: astore_0 
    5: iconst_0 
    6: aload_0 
    7: arraylength 
    8: dup 
    9: istore_1 
    10: anewarray #1; //class DaysOfTheWeek 
    13: dup 
    14: astore_2 
    15: iconst_0 
    16: iload_1 
    17: invokestatic #51; //Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V 
    20: aload_2 
    21: areturn 

public static DaysOfTheWeek valueOf(java.lang.String); 
    Code: 
    0: ldC#1; //class DaysOfTheWeek 
    2: aload_0 
    3: invokestatic #59; //Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; 
    6: checkcast #1; //class DaysOfTheWeek 
    9: areturn 

} 
+0

+1 за то, чтобы доказать это нелегко;). Благодарю. – DougW

1

Я добавлю к ответу Девона, что метод values() добавляется компилятором по определению.
От перечислений tutorial:

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

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