• JAVA代码
public enum EnumTest {
HELLO,WORLD
}
  • 字节码
public final class EnumTest extends java.lang.Enum<EnumTest> {
public static final EnumTest HELLO; public static final EnumTest WORLD; public static EnumTest[] values();
Code:
0: getstatic #1 // Field $VALUES:[LEnumTest;
3: invokevirtual #2 // Method "[LEnumTest;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LEnumTest;"
9: areturn // 从当前方法返回对象引用 // 调用了(EnumTest)java.lang.Enum.valueOf(EnumTest.class,String)
public static EnumTest valueOf(java.lang.String);
Code:
0: ldc #4 // class EnumTest
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class EnumTest
9: areturn static {};
Code:
0: new #4 // class EnumTest
3: dup
4: ldc #7 // String HELLO
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field HELLO:LEnumTest;
13: new #4 // class EnumTest
16: dup
17: ldc #10 // String WORLD
19: iconst_1
20: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
23: putstatic #11 // Field WORLD:LEnumTest;
26: iconst_2
27: anewarray #4 // class EnumTest, 创建一个引用型(如类,接口,数组)的数组,并将其引用值压入栈顶
30: dup
31: iconst_0
32: getstatic #9 // Field HELLO:LEnumTest;获取指定类的静态域,并将其值压入栈顶
35: aastore
36: dup
37: iconst_1
38: getstatic #11 // Field WORLD:LEnumTest;
41: aastore
42: putstatic #1 // Field $VALUES:[LEnumTest;用栈顶的值为指定的类的静态域赋值
45: return
}
  • 参考源码实现的枚举(没有继承 java.lang.Enum):
public final class MyEnum {
private final String s; private MyEnum(String s) {
this.s = s;
} public static final MyEnum HELLO = new MyEnum("HELLO");
public static final MyEnum WORLD = new MyEnum("WORLD"); private static volatile MyEnum[] $VALUES; static {
Field[] fields = MyEnum.class.getFields();
List<Field> list = Arrays.asList(fields);
$VALUES = list.stream().map(field -> {
try {
return field.get(MyEnum.class);
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}).collect(Collectors.toList()).toArray(new MyEnum[fields.length]);
} public static MyEnum[] values() {
return $VALUES;
} public static MyEnum valueOf(String name) throws NoSuchFieldException, IllegalAccessException {
Class<MyEnum> clazz = MyEnum.class;
Field field = clazz.getField(name);
return (MyEnum) field.get(clazz);
} @Override
public String toString() {
return s;
}
}
  • java.lang.Enum类
// Enum 不能直接被继承
// 下列省略部分代码
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable { private final String name; private final int ordinal; public final String name() {
return name;
} public final int ordinal() {
return ordinal;
} protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
} public String toString() {
return name;
} // 比较ordinal值,用于排序
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
} @SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass(); // 获取当前类的Class
Class<?> zuper = clazz.getSuperclass(); // 获取当前类的父类
// 如果父类是Enum.class,则返回当前类的Class,否则返回父类的Class
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
} public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null) return result;
// 为什么不先判断name是否等于null?
if (name == null) throw new NullPointerException("Name is null");
throw new IllegalArgumentException("No enum constant " + enumType.getCanonicalName() + "." + name);
} public final boolean equals(Object var1) {
return this == var1;
}
} public final class Class<T>{ private transient volatile Map<String, T> enumConstantDirectory; // 简单的说生成枚举Map:{"HEELO":EnumTest.HELLO,"WORLD":EnumTest.WORLD}
Map<String, T> enumConstantDirectory() {
Map<String, T> directory = enumConstantDirectory;
if (directory == null) {
T[] universe = getEnumConstantsShared();
if (universe == null)
throw new IllegalArgumentException(getName() + " is not an enum type");
directory = new HashMap<>(2 * universe.length);
for (T constant : universe) {
directory.put(((Enum<?>)constant).name(), constant);
}
enumConstantDirectory = directory;
}
return directory;
} private transient volatile T[] enumConstants; T[] getEnumConstantsShared() {
T[] constants = enumConstants;
if (constants == null) {
// 非Enum 直接返回null
if (!isEnum()) return null;
try {
final Method values = getMethod("values");
// 提升访问修饰
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
values.setAccessible(true);
return null;
}
});
// 反射调用values方法,得到枚举数组
@SuppressWarnings("unchecked")
T[] temporaryConstants = (T[])values.invoke(null);
enumConstants = constants = temporaryConstants;
}catch (InvocationTargetException | NoSuchMethodException |IllegalAccessException ex) {
return null;
}
}
return constants;
} public boolean isEnum() {
// 返回此类或接口以整数编码的 Java语言修饰符,如:public private protected、enum等。
// 如果modifers有enum修饰语ENUM &操作将得到ENUM,不等于0。
return (this.getModifiers() & ENUM) != 0 &&
this.getSuperclass() == java.lang.Enum.class;
}
}
  • 测试
Class<?> aClass = EnumTest.HELLO.getClass();
System.out.println(aClass); // class EnumTest
System.out.println(aClass.getSuperclass()); // class java.lang.Enum
  • 结论

    • 枚举类是一个普通的java类,enum类型只是java的语法糖,编译器帮助开发人员转化为Eunm类。
    • 枚举类继承了java.lang.Enum类,valueOf和values方法继承自Enum类。
    • java.lang.Enum类不能被直接继承,所以自己实现的valueOf的实现采用了反射获取字段。
    • java.lang.Enum类的valueOf实现采用了Class类反射和内部的map缓存。
05-11 22:23