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
相关文章推荐
- Java集合框架成员之HashTable类的源码分析(基于JDK1.8版本)
- 【集合框架】JDK1.8源码分析之HashMap(一)
- 从JDK源码分析Java中的equals与hashCode
- JDK源码分析(二)——LinkedList
- JDK源码分析之多线程同步锁ReentrantLock类源码的探索
- HashMap源码分析(基于JDK1.6)
- 【JDK源码分析】String的存储区与不可变性(转)
- [jjzhu学java]之JDK集合框架源码分析
- 【jdk1.8】String源码分析
- JDK源码分析-AtomicInteger
- ArrayList源码分析(基于JDK1.6)
- 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)
- Java中集合框架,Collection接口、Set接口、List接口、Map接口,已经常用的它们的实现类,简单的JDK源码分析底层实现
- 容器第三课,JDK源码分析,自己实现ArrayList数组扩容
- ArrayList源码分析(JDK1.8)
- JDK源码分析:java.lang.String
- 通过JDK源码角度分析Long类详解
- JDK动态代理源码分析之二
- JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue
- Java基础:JDK动态代理源码分析