java enum(枚舉)使用詳解 + 總結

轉:http://blog.csdn.net/qiyueqinglian/article/details/50738548


DK1.5引入了新的類型——枚舉。在 Java 中它雖然算個“小”功能,卻給我的開發帶來了“大”方便。 
接下來,我以自定義的枚舉類LightsEnum.java和LightsEnumWithValue.java來介紹一下枚舉類的使用。 
LightsEnum.java

package enums;
public enum LightsEnum {
    RED, YELLOW, GREEN
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

用法一:定義常量

在JDK1.5 之前,我們定義常量都是: public static fianl…. 。現在好了,有了枚舉,可以把相關的常量分組到一個枚舉類型裏,而且枚舉提供了比常量更多的方法。 
通過類名就可以直接引用這些常量,比如:LightsEnum.YELLOW

// 遍歷enum
LightsEnum[] lightsEnumArr = LightsEnum.values();
for (LightsEnum e : lightsEnumArr) {
    System.out.println(e.toString());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

運行結果: 
RED 
YELLOW 
GREEN

用法二:與switch結合

JDK1.6之前的switch語句只支持int,char,enum類型,使用枚舉,能讓我們的代碼可讀性更強。

LightsEnum currentLight = LightsEnum.YELLOW;
switch (currentLight) {
case RED:
    System.out.println("this is the red light");
    break;
case YELLOW:
    System.out.println("this is the yellow light");
    break;
case GREEN:
    System.out.println("this is the green light");
    break;
default:
    break;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

運行結果:this is the yellow light

用法三:給 enum 自定義屬性和方法

如果打算自定義方法,那麼必須在enum實例序列的最後添加一個分號。而且 Java 要求必須先定義 enum 實例。 
LightsEnumWithValue.java

package enums;

public enum LightsEnumWithValue {
    RED("紅燈"), YELLOW("黃燈"), GREEN("綠燈");

    // 自定義變量
    private String value;

    // 自定義普通成員方法
    public String getValue() {
        return value;
    }

    // 構造方法
    LightsEnumWithValue(String value) {
        this.value = value;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

使用自定義的變量

LightsEnumWithValue[] lightsEnumWithValueArr = LightsEnumWithValue
                .values();
for (LightsEnumWithValue e : lightsEnumWithValueArr) {
    System.out.println("toString: " + e.toString());
    System.out.println("getValue: " + e.getValue());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

運行結果: 
toString: RED 
getValue: 紅燈 
toString: YELLOW 
getValue: 黃燈 
toString: GREEN 
getValue: 綠燈

用法四:覆蓋枚舉的方法

package enums;

public enum LightsEnumWithValue {
    RED("紅燈"), YELLOW("黃燈"), GREEN("綠燈");

    // 自定義變量
    private String value;

    // 自定義普通成員方法
    public String getValue() {
        return value;
    }

    // 構造方法
    LightsEnumWithValue(String value) {
        this.value = value;
    }

    // 覆蓋方法
    @Override
    public String toString() {
        return this.name() + "_" + this.value;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

調用覆蓋之後的toString方法

LightsEnumWithValue[] lightsEnumWithValueArr = LightsEnumWithValue
                .values();
for (LightsEnumWithValue e : lightsEnumWithValueArr) {
    System.out.println("toString: " + e.toString());
    System.out.println("getValue: " + e.getValue());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

運行結果(注意和用法三中的toString得到的結果不一樣了): 
toString: RED_紅燈 
getValue: 紅燈 
toString: YELLOW_黃燈 
getValue: 黃燈 
toString: GREEN_綠燈 
getValue: 綠燈

用法五:實現接口

所有的枚舉都繼承自java.lang.Enum類。由於Java 不支持多繼承,所以枚舉對象不能再繼承其他類。

public interface Behaviour {  
    void print();  
    String getInfo();  
}  
public enum Color implements Behaviour{  
    RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);  
    // 成員變量  
    private String name;  
    private int index;  
    // 構造方法  
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
    //接口方法  
    @Override  
    public String getInfo() {  
        return this.name;  
    }  
    //接口方法  
    @Override  
    public void print() {  
        System.out.println(this.index+":"+this.name);  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

用法六:使用接口組織枚舉

public interface Food {  
    enum Coffee implements Food{  
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
    }  
    enum Dessert implements Food{  
        FRUIT, CAKE, GELATO  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
如:Food f = Food.Coffee.BLACK_COFFEE;

用法七:EnumSet,EnumMap 的應用

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

EnumSet<LightsEnum> lightsEnumSet = EnumSet.allOf(LightsEnum.class);
for (LightsEnum l : lightsEnumSet) {
    System.out.println(l.toString());
}
System.out.println("------------------EnumMap");
EnumMap<LightsEnum, String> lightsEnumMap = new EnumMap<LightsEnum, String>(
        LightsEnum.class);
lightsEnumMap.put(LightsEnum.RED, "紅燈");
Set<Entry<LightsEnum, String>> set = lightsEnumMap.entrySet();
Iterator<Entry<LightsEnum, String>> iterator = set.iterator();
while (iterator.hasNext()) {
    Entry<LightsEnum, String> e = iterator.next();
    System.out.println(e.getKey().toString() + ":" + e.getValue());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

運行結果: 
——————EnumSet 
RED 
YELLOW 
GREEN 
——————EnumMap 
RED:紅燈

enum總結及常用方法

可以把 enum 看成是一個普通的 class,可以定義一些屬性和方法,實現接口,不同之處是:enum 不能使用 extends 關鍵字繼承其他類,因爲 enum 已經繼承了 java.lang.Enum(java是單一繼承)

// int ordinal() 返回枚舉常量的序數(它在枚舉聲明中的位置,其中初始常量序數爲零)。
System.out.println("red ordinal: " + LightsEnum.RED.ordinal());
System.out.println("yellow ordinal: " + LightsEnum.YELLOW.ordinal());
System.out.println("green ordinal: " + LightsEnum.GREEN.ordinal());

// int compareTo(E o) 比較此枚舉與指定對象的順序
int compToRed = currentLight.compareTo(LightsEnum.RED);
int compToYellow = currentLight.compareTo(LightsEnum.YELLOW);
int compToGreen = currentLight.compareTo(LightsEnum.GREEN);
System.out.println("yellow compare to red: " + compToRed);
System.out.println("yellow compare to yellow: " + compToYellow);
System.out.println("yellow compare to green: " + compToGreen);

// String name() 返回此枚舉常量的名稱,在其枚舉聲明中對其進行聲明
System.out.println("name: " + currentLight.name());

// String toString() 返回枚舉常量的名稱,它包含在聲明中
System.out.println("toString: " + currentLight.toString());

// Class<E> getDeclaringClass() 返回與此枚舉常量的枚舉類型相對應的 Class 對象。
System.out.println("getDeclaringClass(): "
        + currentLight.getDeclaringClass().getName());

// static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
// 返回帶指定名稱的指定枚舉類型的枚舉常量。
System.out.println(LightsEnum.valueOf(LightsEnum.class, "YELLOW"));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

運行結果: 
red ordinal: 0 
yellow ordinal: 1 
green ordinal: 2 
yellow compare to red: 1 
yellow compare to yellow: 0 
yellow compare to green: -1 
name: YELLOW 
toString: YELLOW 
getDeclaringClass(): enums.LightsEnum 
YELLOW

enum原理

語法(定義) 
創建枚舉類型要使用 enum 關鍵字,隱含了所創建的類型都是 java.lang.Enum 類的子類(java.lang.Enum 是一個抽象類)。枚舉類型符合通用模式 Class Enum<E extends Enum<E>>,而 E 表示枚舉類型的名稱。枚舉類型的每一個值都將映射到 protected Enum(String name, int ordinal)構造函數中,在這裏,每個值的名稱都被轉換成一個字符串,並且序數設置表示了此設置被創建的順序。 
enum 的語法結構儘管和 class 的語法不一樣,但是經過編譯器編譯之後產生的是一個class文件。該class文件經過反編譯可以看到實際上是生成了一個類,該類繼承了java.lang.Enum。LightsEnum.java和LightsEnumWithValue.java經過反編譯(javap enums.LightsEnumWithValue 命令)之後得到的內容如下。 
這兩個enum反編譯之後的主要不同是構造函數,LightsEnumWithValue.java中還含有自定義的方法。

private LightsEnum(String s, int i)
    {
        super(s, i);
    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
private LightsEnumWithValue(String s, int i, String value)
    {
        super(s, i);
        this.value = value;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

LightsEnum.class

// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   LightsEnum.java
package enums;
public final class LightsEnum extends Enum
{
    public static final LightsEnum RED;
    public static final LightsEnum YELLOW;
    public static final LightsEnum GREEN;
    private static final LightsEnum ENUM$VALUES[];

    private LightsEnum(String s, int i)
    {
        super(s, i);
    }

    public static LightsEnum[] values()
    {
        LightsEnum alightsenum[];
        int i;
        LightsEnum alightsenum1[];
        System.arraycopy(alightsenum = ENUM$VALUES, 0, alightsenum1 = new LightsEnum[i = alightsenum.length], 0, i);
        return alightsenum1;
    }

    public static LightsEnum valueOf(String s)
    {
        return (LightsEnum)Enum.valueOf(enums/LightsEnum, s);
    }

    static 
    {
        RED = new LightsEnum("RED", 0);
        YELLOW = new LightsEnum("YELLOW", 1);
        GREEN = new LightsEnum("GREEN", 2);
        ENUM$VALUES = (new LightsEnum[] {
            RED, YELLOW, GREEN
        });
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

LightsEnumWithValue.class

// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   LightsEnumWithValue.java

package enums;


public final class LightsEnumWithValue extends Enum
{

    public static final LightsEnumWithValue RED;
    public static final LightsEnumWithValue YELLOW;
    public static final LightsEnumWithValue GREEN;
    private String value;
    private static final LightsEnumWithValue ENUM$VALUES[];

    public String getValue()
    {
        return value;
    }

    private LightsEnumWithValue(String s, int i, String value)
    {
        super(s, i);
        this.value = value;
    }

    public static LightsEnumWithValue[] values()
    {
        LightsEnumWithValue alightsenumwithvalue[];
        int i;
        LightsEnumWithValue alightsenumwithvalue1[];
        System.arraycopy(alightsenumwithvalue = ENUM$VALUES, 0, alightsenumwithvalue1 = new LightsEnumWithValue[i = alightsenumwithvalue.length], 0, i);
        return alightsenumwithvalue1;
    }

    public static LightsEnumWithValue valueOf(String s)
    {
        return (LightsEnumWithValue)Enum.valueOf(enums/LightsEnumWithValue, s);
    }

    static 
    {
        RED = new LightsEnumWithValue("RED", 0, "紅燈");
        YELLOW = new LightsEnumWithValue("YELLOW", 1, "黃燈");
        GREEN = new LightsEnumWithValue("GREEN", 2, "綠燈");
        ENUM$VALUES = (new LightsEnumWithValue[] {
            RED, YELLOW, GREEN
        });
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

參照: 
http://www.cnblogs.com/hemingwang0902/archive/2011/12/29/2306263.html 
http://blog.lichengwu.cn/java/2011/09/26/the-usage-of-enum-in-java/


發佈了0 篇原創文章 · 獲贊 126 · 訪問量 92萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章