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;
}
}
// 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緩存。