Откуда приходит Enum.values ​​()?

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

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

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

public static enum MyEnum 

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

Solutions Collecting From Web of "Откуда приходит Enum.values ​​()?"

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

Как видно из приведенного ниже байт-кода, полученного методом disassemlbing перечисления, метод values() в перечислениях просто возвращает копию private static массива, который содержит всю объявленную константу enum. Этот массив 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 } 

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

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

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

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