Откуда приходит Enum.values ​​()? - PullRequest
8 голосов
/ 06 октября 2010

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

Я проверил исходный код для класса Enum, и не повезло ( есть связанные, частныеМетод "getValues" ).

Итак, я предполагаю, что какой-то компилятор / интерпретатор-foo уже создает класс, расширяющий Enum из объявления, например:

public static enum MyEnum

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

Ответы [ 4 ]

13 голосов
/ 07 октября 2010

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

2 голосов
/ 07 октября 2010

Как видно из приведенного ниже байт-кода, полученного путем разборки перечисления, метод 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

}
1 голос
/ 07 октября 2010

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

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

1 голос
/ 07 октября 2010

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

Oracle Oracle (версия 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. Это заполняется компилятором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...