enum可以定义枚举值,我们通过public enum TestEnum{...} 这样的语句定义一个枚举类型。enum是java的一个保留字,我们似乎没有找到enum的实现代码。不过我们可以通过反编译一个自己定义的枚举类型窥其一斑。
public enum TestEnum {
ONE("one", "1");
private String code;
private String name;
TestEnum(String code, String name) {
this.code = code;
this.name = name;
}
}
这样一个自定义的枚举类型,经过反编译之后得到:
public final class TestEnum extends java.lang.Enum<TestEnum> {
public static final TestEnum ONE;
public static TestEnum[] values();
public static TestEnum valueOf(java.lang.String);
static {};
}
可以看到枚举值的实现方式是一个继承了Enum类型的final类,其中枚举对象都是内部定义的final枚举对象。
源码位置:java.lang.Enum
Enum是一个抽象类,类定义:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {...}
其范型类型是其子类,也就是自己定义的枚举类型。
数据结构
name:用于保存定义的枚举常量的名称,也就是上面例子中的ONE
ordinal: 枚举常量的序数,跟定义时的顺序有关。
方法分析
枚举类中值得探究的方法不是很多,大概看一下:
构造函数:仅有的一个构造函数,使用者无法调用,编译器生成枚举声明的代码时会用到这个构造函数。
valueof方法:根据范型类型和名称获得这个枚举的实例。实际通过Class类中的方法获取枚举值:enumType.enumConstantDirectory().get(name); 其中enumType是Class类型的对象,name是枚举对象的名称。
Class类中维护了一个枚举名称和实例变量的map:private volatile transient Map<String, T> enumConstantDirectory = null;如果这个类是一个枚举类型,那么在枚举类第一次访问valueof方法时,会生成这个map。
Map<String, T> enumConstantDirectory() {
if (enumConstantDirectory == null) {
T[] universe = getEnumConstantsShared();
if (universe == null)
throw new IllegalArgumentException(
getName() + " is not an enum type");
Map<String, T> m = new HashMap<>(2 * universe.length);
for (T constant : universe)
m.put(((Enum<?>)constant).name(), constant);
enumConstantDirectory = m;
}
return enumConstantDirectory;
}
枚举类型的Class时如何获得保存的枚举值的?Class维护了一个枚举类型的数组:private volatile transient T[] enumConstants = null;然后通过调用枚举类中的values方法,将枚举数据赋值给这个变量。
T[] getEnumConstantsShared() {
if (enumConstants == null) {
if (!isEnum()) return null;
try {
final Method values = getMethod("values");
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
values.setAccessible(true);
return null;
}
});
@SuppressWarnings("unchecked")
T[] temporaryConstants = (T[])values.invoke(null);
enumConstants = temporaryConstants;
}
catch (InvocationTargetException | NoSuchMethodException |
IllegalAccessException ex) { return null; }
}
return enumConstants;
}
通过枚举类型生成的values方法,可以获得所有的枚举值。查看反编译代码可以看到枚举类中会生成一个values方法。
静态方法invoke参数为null