我正在浏览文档和源代码,因为我想确定values()总是按照声明枚举值的顺序返回一个数组。事实证明,据我所知,它不是in the documentation。
我检查了Enum类的源代码,但没有运气(there is a related, private "getValues" method)。
所以我猜测一些编译器/解释器-foo已经开始创建一个扩展Enum的类,如下所示:
public static enum MyEnum
在编译期间,values()也被静态转换为硬编码数组吗?或者它实际上是在运行时调用的方法,如果是,它在哪里定义?
答案 0 :(得分:13)
values()
方法是enum
类型定义的一部分。不要与Enum
基类混淆。正式定义在Section 8.9 of the JLS中,它确实指定返回的顺序与它们的声明顺序相匹配。
答案 1 :(得分:2)
从下面通过反汇编枚举获得的字节码可以看出,枚举上的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
}
答案 2 :(得分:1)
您提供的链接(其中有私有getValues
方法)来自Apache Harmony(版本6,这是一个开源Java SE)。它们与Oracle的Enum
类(没有私有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
内声明的枚举值常量。这是由编译器填充的。
答案 3 :(得分:1)
我将添加到Devon的答案中,根据定义,编译器会添加values()
方法。
来自枚举tutorial:
编译器自动添加一些 创建一个特殊的方法 枚举。例如,他们有静态 values方法,返回一个数组 包含所有的值 按照声明的顺序枚举。