java EnumSet源碼學習

1、EnumSet 簡單介紹

一、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內部的元素只能是一種類型

2、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);
}

3、EnumSet之RegularEnumSet的高效之處

首先,在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

相關文章
相關標籤/搜索