Java枚舉

枚舉的概述:

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

 

爲什麼要有枚舉:

         問題:要定義星期幾或性別的變量,該怎麼定義?假設用1-7分別表示星期一到星期日,但有人可能會寫成int weekday=0;

         枚舉就是要讓某個類型的變量的取值只能爲某個固定的值得一個,否則,編譯器就會報錯。枚舉可以讓編譯器在編譯時就可以控制源程序中填寫的非法值,普通變量的方式在開發極端無法發現這一目標。

 

用普通類如何實現枚舉功能,定義一個WeekDay的類來模擬枚舉的功能

        1.  私有的構造方法

         2. 每個元素分別用一個公有的靜態成員變量表示

         3. 可以用若干公有方法或抽象方法,例如,要提供nextDay方法必須是抽象的。

 

小貼士:採用抽象方法定義nextDay就將大量的if-else語句轉移成了一個個獨立的類。

 

publicabstractclassWeekDay {

    //用普通類如何實現枚舉功能

    publicabstract WeekDaynextDay();

   

    public WeekDay() {

       

    }

   

    publicstaticfinal WeekDay SUN = new WeekDay() {

 

        @Override

        public WeekDay nextDay() {

            // TODO Auto-generated method stub

            returnMON;

        }};

    publicstaticfinal WeekDay MON = new WeekDay() {

 

        @Override

        public WeekDay nextDay() {

            // TODO Auto-generated method stub

            returnSUN;

        }};

   

    public String toString() {

        returnthis == SUN ? "SUN" : "MON";

    }

   

}

 

 

 

枚舉的基本應用:

        

枚舉的定義舉例:

 

publicclassEnumTest1 {

 

    publicstaticvoid main(String[] args) {

        WeekDaywd = WeekDay.FRI;

        //枚舉就是一個對象,

        System.out.println(wd);

        //打印出名字

        System.out.println(wd.name());

        //打印出順序

        System.out.println(wd.ordinal());

        //給你傳過來一個SUN,得到一個枚舉對象

        System.out.println(WeekDay.valueOf("SUN").toString());

        //返回一個枚舉的數組

        System.out.println(WeekDay.values().length);

    }

    publicenum WeekDay {

        SUN,MON,TUE,WED,THI,FRI,SAT;

    }

}

 

枚舉也是一個類(在編譯出的class文件中可以看到枚舉是一個單獨的類的形式存在的),其中也可以定義構造方法、成員變量、普通方法和抽象方法。

 

帶有構造方法的枚舉:

         在枚舉對象的後面跟一個括號,跟上你需要使用的是哪個構造方法

 

枚舉的語法:枚舉元素必須位於枚舉體中最開始部分,枚舉元素列表後面要有分號與其他成員分割。把枚舉中的成員方法或成員變量等放在枚舉元素的前面,編譯器報告錯誤。


帶構造方法的枚舉

         構造方法必須定義爲私有的

         如果有多個構造方法,該如何選擇哪個構造方法,參數列表

         枚舉元素MON和MON()的效果一樣,都是默認的構造方法

        

帶構造方法的枚舉舉例如下

publicclassEnumTest2 {

 

    publicstaticvoid main(String[] args) {

        WeekDaywd = WeekDay.FRI;

        //枚舉就是一個對象,

        System.out.println(wd);

        //打印出名字

        System.out.println(wd.name());

        //打印出順序

        System.out.println(wd.ordinal());

        //給你傳過來一個SUN,得到一個枚舉對象

        System.out.println(WeekDay.valueOf("SUN").toString());

        //返回一個枚舉的數組

        System.out.println(WeekDay.values().length);

    }

 

    publicenum WeekDay {

        //在枚舉對象的後面跟一個括號,跟上你需要使用的是哪個構造方法

        SUN(),MON(1),TUE,WED,THI,FRI,SAT;

        private WeekDay() {

            System.out.println("first");

        }

        private WeekDay(int day) {

            System.out.println("second");

        }

    }

 

}

 

 

實現帶有抽象方法的枚舉:

 

帶方法的枚舉

     定義枚舉TrafficLamp

    實現普通的next方法

    實現抽象的next方法,每個元素分別由枚舉類的子類來生成的實例對象,這些子類採用類似內部類的方式進行定義


publicenumTrafficLamp {

        //使用抽象方法可以避免使用大量的if-else

        RED(30) {

            @Override

            public TrafficLamp nextLamp(){

                // TODO Auto-generated method stub

                returnGREEN;

            }

        },

        GREEN(45) {

            @Override

            public TrafficLamp nextLamp(){

                // TODO Auto-generated method stub

                returnYELLOW;

            }

        },

        YELLOW(5) {

            @Override

            public TrafficLamp nextLamp(){

                // TODO Auto-generated method stub

                returnRED;

            }

        };

        publicabstract TrafficLampnextLamp();

        privateinttime;

        private TrafficLamp(int time) {

            this.time = time;

        }

    }

 

枚舉只有一個成員時,就可以作爲單例的實現(比如要表示一個開關的狀態,ONOFF時)

 

 

總結:通常定義常量方法和枚舉定義常量方法區別

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

1.    代碼:

public class State{

public staticfinal int ON = 1;

public staticfinal 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 ofResponsibility) . 這個關係到設計模式的職責鏈模式。以多種不同的方法來解決一個問題。然後將他們鏈接在一起。當一個請求到來時,遍歷這個鏈,直到鏈中的某個解決方案能夠處理該請求。

 

10.   使用enum 的狀態機

 

11.   使用enum 多路分發

 

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