天天看點

Java枚舉類型enum

枚舉的文法

1.Enum的全稱為enumeration,中文俗稱枚舉類,學過C/C++等語言的人,應該都對它略知一二。

    但在Java語言規範中,是在JDK 5版本中才引入的,存放在 java.lang 包中。在Java版的Enum實質是文法糖,其聲明方式如下:

【代碼1】

  enum是用來聲明枚舉的關鍵字,聲明定義的類都隐含繼承了一個父類(java.lang.Enum<E>),是以枚舉不能再繼承,但仍可實作接口。

    該父類有兩個私有屬性name(枚舉類型的名稱)和ordinal(枚舉執行個體被建立的序數),分别通過name()和ordinal()暴露出來了.

    定義在枚舉類型裡的每一個枚舉執行個體都将映射到Enum的子類中,其執行個體的名稱和在枚舉類型裡定義的順序都會傳入到這個構造函數裡 : protected Enum(String name, int ordinal)。

2.如果想更清楚了解一下Enum,可以用反編譯工具把自己定義的枚舉反編譯一下就一目了然了,它就是一個普通的類,隻是Java語言規範從Code角度進行了限制,執行javap com.enumtest.Color指令如下:

【代碼2】

3.所有枚舉類都繼承了Enum的方法,下面我們詳細介紹這些方法。

(1) ordinal()方法: 傳回枚舉值在枚舉類種的順序。這個順序根據枚舉值聲明的順序而定。

    Color.RED.ordinal(); //傳回結果:0

    Color.BLUE.ordinal(); //傳回結果:1

(2) compareTo()方法: Enum實作了java.lang.Comparable接口,是以可以比較象與指定對象的順序。Enum中的compareTo傳回的是兩個枚舉值的順序之差。當然,前提是兩個枚舉值必須屬于同一個枚舉類,否則會抛出ClassCastException()異常。(具體可見源代碼)

    Color.RED.compareTo(Color.BLUE); //傳回結果 -1

(3) values()方法: 靜态方法,傳回一個包含全部枚舉值的數組。

    Color[] colors=Color.values();

    for(Color c:colors){

        System.out.print(c+",");

    }//傳回結果:RED,BLUE,BLACK YELLOW,GREEN,

(4) toString()方法: 傳回枚舉常量的名稱。

    Color c=Color.RED;

    System.out.println(c);//傳回結果: RED

(5) valueOf()方法: 這個方法和toString方法是相對應的,傳回帶指定名稱的指定枚舉類型的枚舉常量。

    Color.valueOf("BLUE"); //傳回結果: Color.BLUE

(6) equals()方法: 比較兩個枚舉類對象的引用。

4. 如果定義的枚舉有自己的構造函數必須聲明私有的。

5. 注意以下差別:

【代碼3】

在enum Color3中是一個空的枚舉;在enum Color4和Color5中有一個RED的枚舉值,後面可以加分号或者不加分号;如果在枚舉值後面添加方法,那麼在枚舉值的最後添加一個分号,如enum Color6;如果像enum Color7一樣想把枚舉值定義在方法後面是非法的,編譯器會提示錯誤;當然也可以像enum Color8一樣定義,注意方法test()之前的分号。

枚舉的用法

(1) 常用于對同一類常量進行分類。見代碼1.

(2) 聲明接口方法時,輸入參數類型采用枚舉比用原始類型值常量更嚴謹.

(3) 常量有時往往不僅僅隻是一個值,有可能會包含多個屬性,此時很适合用枚舉

(4) 有時常量對象需要從配置檔案中讀取其描述資訊或者UI顯示資訊,此時也适合用枚舉

(5) 從Java文法層面來說,枚舉可以在switch使用,在if中可直接進行比較 。

【代碼4】

運作結果:

(6) 聲明枚舉屬性時最好用public final修飾,使用起來會非常友善

(7) 自定義枚舉時,建議不要使用自帶的name()和ordinal()方法傳回值來與原始值類型轉換,這樣業務不依賴其枚舉的名字和順序

【代碼5】

運作結果:紅色

(8) 重載枚舉的方法toString

【代碼6】

(9)實作接口。所有的枚舉都繼承自java.lang.Enum類。由于java不支援多繼承,是以枚舉對象不能再繼承其他的類。

【代碼7】

【代碼8】

(10) 可以建立一個enum類,把它看做一個普通的類。除了它不能繼承其他類。(Java是單繼承,它已經繼承了Enum),可以添加其他的方法,覆寫它本身的方法。

(11) values()方法是編譯器插入到enum定義中的static方法,是以,當你将enum執行個體向上轉型為父類Enum是,values()就不可通路了。解決辦法:在Class中有一個getEnumConstants()方法,是以即便Enum接口中沒有values()方法,我們仍然可以通過Class對象取得所有的enum執行個體。

【代碼9】

(12) 無法從enum繼承子類,如果需要擴充enum中的元素,在一個接口的内部,建立實作該接口的枚舉,以此将元素進行分組。達到将枚舉元素進行分組。

【代碼10】

(13) java.util.EnumSet和java.util.EnumMap是兩個枚舉集合。EnumSet保證集合中的元素不重複;EnumMap中的 key是enum類型,而value則可以是任意類型。

【代碼11】

運作結果:(略)

(14) 使用enum的職責鍊(Chain of Responsibility) .這個關系到設計模式的職責鍊模式。以多種不同的方法來解決一個問題。然後将他們連結在一起。當一個請求到來時,周遊這個鍊,直到鍊中的某個解決方案能夠處理該請求。