您的位置:首页 > 编程语言 > Java开发

jdk源码分析--Enum

2017-08-12 10:59 274 查看
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;
}
// These can happen when users concoct enum-like classes
// that don't comply with the enum spec.
catch (InvocationTargetException | NoSuchMethodException |
IllegalAccessException ex) { return null; }
}
return enumConstants;
}


通过枚举类型生成的values方法,可以获得所有的枚举值。查看反编译代码可以看到枚举类中会生成一个values方法。
静态方法invoke参数为null
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jdk java 源码 反编译