一、A specialized Set implementation for use with enum types. 二、All of the elements in an enum set must come from a single enum type that is specified, explicitly or implicitly, when the set is created. EnumSet是Set的一种实现,它必需要配合枚举使用,而且EnumSet内部的元素只能是一种类型
EnumSet是一个抽象类,内部多处采用静态工厂方法。它不对外提供构造函数,只能经过一系列静态方法,如of(...)、noneOf(...)、copyOf(...)、complementOf(...)来获取对象实例。这样作的好处是它对外封装了内部实现,如EnumSet返回的真正的类型是它的子类:RegularEnumSet
或者JumboEnumSet
,但外部使用者并不知道这些,当EnumSet API升级时,如添加一个子类实现,原先引用的地方不用发生改变。数组
//核心方法,其余获取EnumSet实例的方法都调用了这个方法 public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { Enum<?>[] universe = getUniverse(elementType); if (universe == null) throw new ClassCastException(elementType + " not an enum"); if (universe.length <= 64) return new RegularEnumSet<>(elementType, universe); else return new JumboEnumSet<>(elementType, universe); }
首先,在EnumSet内部,有一个成员变量final Enum<?>[] universe;
,它持有该EnumSet中的元素所对应的枚举类型的全部值(实例),当调用noneOf()
方法时,都会调用getUniverse()
获取到枚举类型的全部实例,并赋值给universe
变量。而后在RegularEnumSet子类中,有一个成员变量private long elements
,能够根据elements的值进行位运算获得的结果,到universe
数组取得相应的元素。当要添加元素或者删除元素时,也只须要改变elements的值便可。函数
/** * Returns all of the values comprising E. * The result is uncloned, cached, and shared by all callers. */ private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) { return SharedSecrets.getJavaLangAccess() .getEnumConstantsShared(elementType); }
/** * Returns <tt>true</tt> if this set contains the specified element. */ public boolean contains(Object e) { if (e == null) return false; Class<?> eClass = e.getClass(); if (eClass != elementType && eClass.getSuperclass() != elementType) return false; return (elements & (1L << ((Enum<?>)e).ordinal())) != 0; } /** * Adds the specified element to this set if it is not already present. */ public boolean add(E e) { typeCheck(e); long oldElements = elements; elements |= (1L << ((Enum<?>)e).ordinal()); return elements != oldElements; }
一、JumboEnumSet
后面可能会再研究
二、若有不正确或者想交流的地方,欢迎指出this