Java5 枚舉類型使用總結 !

 
一、概述

枚舉(enum)類型是Java 5新增的特性,它是一種新的類型,允許用常量來表示特定的數據片斷,而且全部都以類型安全的形式來表示。Tiger 專家、developerWorks 的多產作者 Brett McLaughlin 將解釋枚舉的定義,介紹如何在應用程序中運用枚舉,以及它爲什麼能夠讓您拋棄所有舊的 public static final 代碼。
 
枚舉在什麼地方適用呢?一條普遍規則是,任何使用常量的地方,例如目前用 switch 代碼切換常量的地方。如果只有單獨一個值(例如,鞋的最大尺寸,或者籠子中能裝猴子的最大數目),則還是把這個任務留給常量吧。但是,如果定義了一組值,而這些值中的任何一個都可以用於特定的數據類型,那麼將枚舉用在這個地方最適合不過。
 
二、在枚舉類型之前,Java是如何實現枚舉功能的

在枚舉類型出現之前,java是通過在接口或者類中定義public static final 的變量來實現的。比如,對於經典的紅色警戒2中的英國狙擊(sharp-shooter)手三個動作的描述:
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 8:53:04
* 狙擊手活動
*/
public interface SharpShooter_1 {
    public static final int LOCKED = 1;     //鎖定
    public static final int AIM = 2;        //瞄準
    public static final int SHOOT = 3;      //射擊
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 9:03:50
* 測試方法
*/
public class TestDemo_1 {
    public static void main(String args[]) {
        TestDemo_1 test = new TestDemo_1();
        test.doAction(1);
        test.doAction(2);
        test.doAction(3);
        test.doAction(4);
    }

    /**
     * 執行的動作
     * @param action
     */
    public void doAction(int action) {
        switch (action) {
            case SharpShooter_1.LOCKED:
                System.out.println("1:鎖定目標");
                break;
            case SharpShooter_1.AIM:
                System.out.println("2:瞄準目標");
                break;
            case SharpShooter_1.SHOOT:
                System.out.println("3:射擊");
                break;
            default:
                System.out.println("×:遊戲還沒有定義此動作!");
        }
    }
}
 
運行結果:
1:鎖定目標
2:瞄準目標
3:射擊
×:遊戲還沒有定義此動作!
 
[說明]:當然SharpShooter_1也可以聲明爲class,還可以直接將常量定義到TestDemo_1中,如果常量只是在類內部使用,就聲明爲private或者是protected,如果聲明爲public,則通常是與類功能相聯繫的常數。
 
[注意]:switch語句的條件只能接收數值或字符(byte、short、int或char)或枚舉(enum)類型的變量名或表達式。如果沒有符合條件數值或字符,則執行default語句,default語句不是必須的,如果沒有默認要處理的動作,則default語句可省略。break語句的作用是跳出循環塊。

三、枚舉類型的等價實現
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 10:10:41
* 狙擊手活動(枚舉類型實現)
*/
public enum SharpShooter_2 {
    LOCKED,
    AIM,
    SHOOT
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 10:12:40
* 測試普通枚舉類型
*/
public class TestDemo_2 {

    public static void main(String args[]){
        TestDemo_2 test=new TestDemo_2();
        test.doAction(SharpShooter_2.LOCKED);
        test.doAction(SharpShooter_2.AIM);
        test.doAction(SharpShooter_2.SHOOT);
    }
    /**
     * 執行的動作
     * @param action
     */
    public void doAction(SharpShooter_2 action) {
        switch (action) {
            case LOCKED:
                System.out.println("1:鎖定目標");
                break;
            case AIM:
                System.out.println("2:瞄準目標");
                break;
            case SHOOT:
                System.out.println("3:射擊");
                break;
            default:
                System.out.println("×:遊戲還沒有定義此動作!");
        }
    }
}
 
運行結果:
 
1:鎖定目標
2:瞄準目標
3:射擊
 
三、枚舉類型的實質
 
在編譯SharpShooter_2.java後,會生成一個SharpShooter_2.class文件,這說明枚舉類型的實質還是一個類。因此,在某種程度上,enum關鍵字的作用就是class或者interface。
 
當使用enum定義一個枚舉類型時,實際上所定義的類型自動繼承了java.lang.Enum類。而每個被枚舉的成員實質就是一個枚舉類型的實例,他們默認都是public static final的。可以直接通過枚舉類型名直接使用它們。
 
在查詢JDK1.5文檔的java.lang.Enum類,裏面清楚的說明:java.lang.Enum類是所有 Java 語言枚舉類型的公共基本類。因此,所有枚舉類型都擁有有java.lang.Enum類所提供的共有方法。因此,要學會使用枚舉,還必須認識java.lang.Enum類。下面將詳細說明。
 
四、java.lang.Enum類
 
public abstract class Enum<E extends Enum<E>>extends Objectimplements Comparable<E>, Serializable這是所有 Java 語言枚舉類型的公共基本類。
 
------------------
構造方法摘要
protected Enum(String name,int ordinal)
    單獨的構造方法。程序員無法調用此構造方法。該構造方法用於由響應枚舉類型聲明的編譯器發出的代碼。
 
    參數:
    name - - 此枚舉常量的名稱,它是用來聲明該常量的標識符。
    ordinal - - 枚舉常量的序數(它在枚舉聲明中的位置,其中初始常量序數爲零)。
 
------------------
方法摘要
 
protected  Object clone()
          拋出 CloneNotSupportedException。
 
 int compareTo(E o)
          比較此枚舉與指定對象的順序。在該對象小於、等於或大於指定對象時,分別返回負整數、零或正整數。 枚舉常量只能與相同枚舉類型的其他枚舉常量進行比較。該方法實現的自然順序就是聲明常量的順序。 
 
 boolean equals(Object other)
          當指定對象等於此枚舉常量時,返回 true。
 
 Class<E> getDeclaringClass()
          返回與此枚舉常量的枚舉類型相對應的 Class 對象。當且僅當 e1.getDeclaringClass() == e2.getDeclaringClass() 時,兩個枚舉常量 e1 和 e2 的枚舉類型才相同。(由該方法返回的值不同於由 Object.getClass() 方法返回的值,Object.getClass() 方法用於帶有特定常量的類主體的枚舉常量。) 
 
 int hashCode()
          返回枚舉常量的哈希碼。
 
 String name()
          返回此枚舉常量的名稱,在其枚舉聲明中對其進行聲明。 與此方法相比,大多數程序員應該優先考慮使用 toString() 方法,因爲 toString 方法返回更加用戶友好的名稱。該方法主要設計用於特殊情形,其正確性取決於獲得正確的名稱,其名稱不會隨版本的改變而改變
 
 int ordinal()
          返回枚舉常量的序數(它在枚舉聲明中的位置,其中初始常量序數爲零)。 大多數程序員不會使用此方法。它被設計用於複雜的基於枚舉的數據結構,比如 EnumSet 和 EnumMap。 
 
 String toString()
          返回枚舉常量的名稱,它包含在聲明中。
 
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
          返回帶指定名稱的指定枚舉類型的枚舉常量。名稱必須與在此類型中聲明枚舉常量所用的標識符完全匹配。(不允許使用額外的空白字符。)
 
   參數:
   enumType - 要從中返回常量的枚舉類型的 Class 對象
   name - 要返回的常量名稱 
 
注意:ordinal() 方法得到枚舉順序的索引,默認從0開始。
五、枚舉的高級用法
 
1、枚舉方法
 
既然枚舉的本質是類,那麼定義枚舉類型時也可以定義方法。比如:
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 11:29:23
* 帶方法的枚舉類型
*/
public enum SharpShooter_3 {
    LOCKED,
    AIM,
    SHOOT;

    public String getDesc() {
        switch (this.ordinal()) {
            case 0:
                return "鎖定目標";
            case 1:
                return "瞄準目標";
            case 2:
                return "射擊";
            default:
                return "沒有該枚舉值!";
        }
    }
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 11:32:40
* 測試枚舉方法
*/
public class TestDemo_3 {
    public static void main(String args[]) {
        for (SharpShooter_3 enumSS : SharpShooter_3.values()) {
            System.out.println(enumSS + " " + enumSS.getDesc());
        }
    }
}
 
運行結果:
LOCKED 鎖定目標
AIM 瞄準目標
SHOOT 射擊

Process finished with exit code 0
 
 
2、枚舉構造方法

 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 11:37:20
* 帶私有構造方法的枚舉類型
*/
public enum SharpShooter_4 {
    LOCKED("鎖定目標"),
    AIM("瞄準目標"),
    SHOOT("射擊");

    private String desc;        //枚舉說明

    /**
     * 私有的構造方法
     */
    private SharpShooter_4(String desc){
        this.desc=desc;
    }

    /**
     * 獲取枚舉值的說明
     * @return String
     */
    public String getDesc(){
        return desc;
    }
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 11:42:50
* 測試帶私有構造方法的枚舉類型
*/
public class TestDemo_4 {
    public static void main(String args[]) {
        for (SharpShooter_4 enumSS : SharpShooter_4.values()) {
            System.out.println(enumSS + " " + enumSS.getDesc());
        }
    }
}
 
運行結果:
LOCKED 鎖定目標
AIM 瞄準目標
SHOOT 射擊

Process finished with exit code 0
 
3、實現接口的枚舉
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 13:59:47
* 說明接口
*/
public interface IDesc {
    /**
     * 獲取說明信息
     * @return String
     */
    public String getDesc();
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 13:43:22
* 實現了接口的枚舉類型
*/
public enum SharpShooter_5 implements IDesc {
    LOCKED("鎖定目標"),
    AIM("瞄準目標"),
    SHOOT("射擊");

    private String desc;        //枚舉說明

    /**
     * 私有的構造方法
     */
    private SharpShooter_5(String desc) {
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 14:03:26
* 測試實現了接口的枚舉類型
*/
public class TestDemo_5 {
    public static void main(String args[]) {
        for (SharpShooter_5 enumSS : SharpShooter_5.values()) {
            System.out.println(enumSS + " " + enumSS.getDesc());
        }
    }
}
 
運行結果:
LOCKED 鎖定目標
AIM 瞄準目標
SHOOT 射擊

Process finished with exit code 0

4、每個枚舉值實現的自己的接口

 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 14:05:48
* 每個枚舉值自己實現接口
*/
public enum SharpShooter_6 implements IDesc {
    LOCKED(){
        public String getDesc() {
            return "鎖定目標";
        }
    },

    AIM{
        public String getDesc() {
            return "瞄準目標";
        }
    },

    SHOOT{
        public String getDesc() {
            return "射擊";
        }
    }
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 14:10:28
* 測試每個枚舉值自己實現接口
*/
public class TestDemo_6 {
    public static void main(String args[]) {
        for (SharpShooter_6 enumSS : SharpShooter_6.values()) {
            System.out.println(enumSS + " " + enumSS.getDesc());
        }
    }
}
 
運行結果:
LOCKED 鎖定目標
AIM 瞄準目標
SHOOT 射擊

Process finished with exit code 0
 
5、帶有抽象方法的枚舉類型
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 14:13:25
* 帶有抽象方法的枚舉類型
*/
public enum SharpShooter_7 {
    LOCKED(){
        public String getDesc() {
            return "鎖定目標";
        }
    },

    AIM{
        public String getDesc() {
            return "瞄準目標";
        }
    },

    SHOOT{
        public String getDesc() {
            return "射擊";
        }
    };

    /**
     * 抽象方法,每個枚舉值都必須自己實現
     *
     * @return String
     */
    public abstract String getDesc();
}
 
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-29
* Time: 14:16:56
* 測試帶有抽象方法的枚舉類型
*/
public class TestDemo_7 {
    public static void main(String args[]) {
        for (SharpShooter_7 enumSS : SharpShooter_7.values()) {
            System.out.println(enumSS + " " + enumSS.getDesc());
        }
    }
}
 
運行結果:
LOCKED 鎖定目標
AIM 瞄準目標
SHOOT 射擊

Process finished with exit code 0
 
六、對Java枚舉類型的一些看法
 
枚舉的本質是類,在沒有枚舉之前,仍然可以按照java最基本的編程手段來解決需要用到枚舉的地方。枚舉屏蔽了枚舉值的類型信息,不像在用public static final定義變量必須指定類型。枚舉是用來構建常量數據結構的模板,這個模板可擴展。枚舉的使用增強了程序的健壯性,比如在引用一個不存在的枚舉值的時候,編譯器會報錯。枚舉的更多用法還需要在開發中去研究創造,Java5、Java6增加了不少新的特性,技術在升級,對程序員來說就要學習,如果你熱愛java的話。否則別人用到新特性的代碼你看不懂,那才叫鬱悶。
 
目前,本人在開發中也很少用到枚舉,雖然Java設計得很好,處心積慮爲開發人員着想,但是是否有必要增加一個關鍵字讓全世界的java程序員去學習研究?本人感覺Java現在越來越複雜了,新特性對我而言是一大障礙,需要大量的時間去熟悉?對此,我也不敢妄下結論,一是我們和java科學家差距太大,二是怕誤導讀者,這個就留個各位讀者吧!
 
發佈了13 篇原創文章 · 獲贊 2 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章