Java列舉型別enum的詳解及使用

xbs525發表於2021-10-22

Java列舉型別enum的詳解及使用

最近跟同事討論問題的時候,突然同事提到我們為什麼Java 中定義的常量值不採用enmu 列舉型別,而採用public final static 型別來定義呢?以前我們都是採用這種方式定義的,很少採用enum 定義,所以也都沒有注意過,面對突入起來的問題,還真有點不太清楚為什麼有這樣的定義。既然不明白就抽時間研究下吧。

Java 中的列舉型別採用關鍵字enum 來定義,從jdk1.5才有的新型別,所有的列舉型別都是繼承自Enum 型別。要了解列舉型別,建議大家先開啟jdk 中的Enum 類簡單讀一下,這個類裡面定義了很多protected 方法,比如建構函式,如果要使用這些方法我們可以把列舉型別定義到當前類中。每個列舉型別,都有自己的名字和順序,當我們輸出一個列舉型別的時候,會輸入列舉型別的name ,具體可以參考下面的例子。

一、   通常定義常量方法

我們通常利用public final static 方法定義的程式碼如下,分別用1 表示紅燈,3 表示綠燈,2 表示黃燈。

package com.csdn.myEnum;public class Light {  /* 紅燈 */  public final static int RED =1;  /* 綠燈 */  public final static int GREEN =3;  /* 黃燈 */  public final static int YELLOW =2;}

 二、   列舉型別定義常量方法

列舉型別的簡單定義方法如下,我們似乎沒辦法定義每個列舉型別的值。比如我們定義紅燈、綠燈和黃燈的程式碼可能如下:

public enum Light {    RED , GREEN , YELLOW ;}

我們只能夠表示出紅燈、綠燈和黃燈,但是具體的值我們沒辦法表示出來。別急,既然列舉型別提供了建構函式,我們可以通過建構函式和覆寫toString 方法來實現。首先給Light 列舉型別增加構造方法,然後每個列舉型別的值通過建構函式傳入對應的引數,同時覆寫toString 方法,在該方法中返回從建構函式中傳入的引數,改造後的程式碼如下:

public enum Light {    // 利用建構函式傳參    RED (1), GREEN (3), YELLOW (2);     // 定義私有變數    private int nCode ;     // 建構函式,列舉型別只能為私有    private Light( int _nCode) {      this . nCode = _nCode;    }     @Override    public String toString() {      return String.valueOf ( this . nCode );    }  }

三、   完整示例程式碼

列舉型別的完整演示程式碼如下:

package com.csdn.myEnum; import java.util.EnumMap;import java.util.EnumSet; public class LightTest {   // 1. 定義列舉型別  public enum Light {    // 利用建構函式傳參    RED (1), GREEN (3), YELLOW (2);     // 定義私有變數    private int nCode ;     // 建構函式,列舉型別只能為私有    private Light( int _nCode) {      this . nCode = _nCode;    }     @Override    public String toString() {      return String.valueOf ( this . nCode );    }  }   /**   * @param args   */  public static void main(String[] args ) {     // 1. 遍歷列舉型別    System. out .println( " 演示列舉型別的遍歷 ......" );    testTraversalEnum ();     // 2. 演示 EnumMap 物件的使用    System. out .println( " 演示 EnmuMap 物件的使用和遍歷 ....." );    testEnumMap ();     // 3. 演示 EnmuSet 的使用    System. out .println( " 演示 EnmuSet 物件的使用和遍歷 ....." );    testEnumSet ();  }   /**   * 演示列舉型別的遍歷   */  private static void testTraversalEnum() {    Light[] allLight = Light.values ();    for (Light aLight : allLight) {      System. out .println( " 當前燈 name : " + aLight.name());      System. out .println( " 當前燈 ordinal : " + aLight.ordinal());      System. out .println( " 當前燈: " + aLight);    }  }   /**   * 演示 EnumMap 的使用, EnumMap 跟 HashMap 的使用差不多,只不過 key 要是列舉型別   */  private static void testEnumMap() {    // 1. 演示定義 EnumMap 物件, EnumMap 物件的建構函式需要引數傳入 , 預設是key 的類的型別    EnumMap<Light, String> currEnumMap = new EnumMap<Light, String>(       Light. class );    currEnumMap.put(Light. RED , " 紅燈 " );    currEnumMap.put(Light. GREEN , " 綠燈 " );    currEnumMap.put(Light. YELLOW , " 黃燈 " );     // 2. 遍歷物件    for (Light aLight : Light.values ()) {      System. out .println( "[key=" + aLight.name() + ",value="         + currEnumMap.get(aLight) + "]" );    }  }   /**   * 演示 EnumSet 如何使用, EnumSet 是一個抽象類,獲取一個型別的列舉型別內容<BR/>   * 可以使用 allOf 方法   */  private static void testEnumSet() {    EnumSet<Light> currEnumSet = EnumSet.allOf (Light. class );    for (Light aLightSetElement : currEnumSet) {      System. out .println( " 當前 EnumSet 中資料為: " + aLightSetElement);    }   }}

執行結果如下:

演示列舉型別的遍歷 ......當前燈 name : RED當前燈 ordinal : 0當前燈: 1當前燈 name : GREEN當前燈 ordinal : 1當前燈: 3當前燈 name : YELLOW當前燈 ordinal : 2當前燈: 2演示 EnmuMap 物件的使用和遍歷 .....[key=RED,value= 紅燈 ][key=GREEN,value= 綠燈 ][key=YELLOW,value= 黃燈 ]演示 EnmuSet 物件的使用和遍歷 .....當前 EnumSet 中資料為: 1當前 EnumSet 中資料為: 3當前 EnumSet 中資料為: 2

 四、   通常定義常量方法和列舉定義常量方法區別

以下內容可能有些無聊,但絕對值得一窺

1.    程式碼:

public class State {public static final int ON = 1;public static final Int OFF= 0;}

有什麼不好了,大家都這樣用了很長時間了,沒什麼問題啊。

首先,它不是型別安全的。你必須確保是int

其次,你還要確保它的範圍是0 和1

最後,很多時候你列印出來的時候,你只看到 1 和0 ,

但其沒有看到程式碼的人並不知道你的企圖,拋棄你所有舊的public static final 常量吧

2.    可以建立一個enum 類,把它看做一個普通的類。除了它不能繼承其他類了。(java 是單繼承,它已經繼承了Enum),
可以新增其他方法,覆蓋它本身的方法

3.    switch() 引數可以使用enum 了

4.    values() 方法是編譯器插入到enum 定義中的static 方法,所以,當你將enum 例項向上轉型為父類Enum是,values() 就不可訪問了。解決辦法:在Class 中有一個getEnumConstants() 方法,所以即便Enum 介面中沒有values() 方法,我們仍然可以通過Class 物件取得所有的enum 例項

5.    無法從enum 繼承子類,如果需要擴充套件enum 中的元素,在一個介面的內部,建立實現該介面的列舉,以此將元素進行分組。達到將列舉元素進行分組。

6.    使用EnumSet 代替標誌。enum 要求其成員都是唯一的,但是enum 中不能刪除新增元素。

7.    EnumMap 的key 是enum ,value 是任何其他Object 物件。

8.    enum 允許程式設計師為eunm 例項編寫方法。所以可以為每個enum 例項賦予各自不同的行為。

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

10.   使用enum 的狀態機

11.   使用enum 多路分發

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支援!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70008343/viewspace-2838809/,如需轉載,請註明出處,否則將追究法律責任。

相關文章