枚舉是僅允許特定數據類型值的有限集合。例如咱們平時生活中星期一到星期日這七天就是一個特定的有限集合,一年四季的春夏秋冬也一樣是的,它們都是枚舉。枚舉和咱們數學中的集合很是類似,若是咱們定義一個Season={Spring、Summer、Autumn、Winner}這樣的集合,當咱們要從集合中取出數據時,只能從集合中有的值來取,不然就會找不到。java
枚舉類也就顧名思義,枚舉類:類的對象是有限和固定的集合。枚舉類是JDK1.5中才出現的新特性,在Java中用enum關鍵字來修飾,enum的全稱是enumeration。全部被enum修飾的類都會默認的繼承自java.lang.Enum這個類,而不是Object類。spring
有的人並不推薦使用枚舉。而有的人推薦使用,認爲枚舉使用方便。這裏就要說上一句仁者見仁智者見智吧。總之,知識裝進本身的腦殼總不會丟,因此咱們先學會它再說。數組
咱們知道枚舉類是JDK1.5纔有的特性,那麼在以前是怎麼來定義的呢?咱們來回顧一下:安全
public class EnumTest { public static final String SPRING="SPRING"; public static final String SUMMER="SUMMER"; public static final String AUTUMN="AUTUMN"; public static final String WINTER="WINTER"; public static void main(String[] args) { System.out.println(EnumTest.SPRING); System.out.println(EnumTest.SUMMER); show(EnumTest.SPRING); show("enum..."); } public static void show(String season){ System.out.println(season); } }
在沒有枚舉類以前咱們使用public static final修飾的全局常量來表示枚舉,雖然這樣能夠達到效果,可是也會存在缺陷。ide
①、類型不安全。若一個方法中要求傳入season這個參數,使用常量的話,形參就是String類型,而開發者能夠傳入任何String類型的值,可是若是是枚舉類型的話,就只能傳入枚舉類中包含的對象。學習
②、代碼複雜。若是咱們定義時是這樣定義常量的 public static final int SPRING=1。而咱們要的結果是輸出SPRING這個字符串,那麼咱們還要在方法中進行大量if else 判斷,以下所示。this
if (season==1){ System.out.println("SPRING"); } ......
而使用枚舉類就不會存在以上問題,話很少說,直接上代碼示例:spa
public enum Season { SPRING, SUMMER, AUTUMN, WINNER }
對,沒錯,代碼量就是這麼的少。咱們使用枚舉類會讓代碼更加直觀,類型更安全,代碼量更少。可是要注意:在枚舉類中聲明枚舉變量時,最前面不能含有任何變量,方法,構造器等內容,也就是說枚舉變量必須聲明在第一行。多個對象之間須要用逗號隔開,若是枚舉變量沒有參數(如SPRING(1),後面會講),分號能夠省略。code
再來看看枚舉類的簡單使用:對象
public static void main(String[] args) { Season spring = Season.SPRING; System.out.println(spring); show(spring); } public static void show(Season season){ System.out.println(season); }
像上述代碼那樣,咱們能夠直接使用枚舉類名稱 . 對象名稱來引用枚舉的值,這即是枚舉類型的最簡單的使用。
在以前的switch語法中只支持int和char類型的數據,可是隨着枚舉類型的出現,enum類型也能夠在switch中使用了,咱們看一下怎麼在switch語句中使用:
public enum Season { SPRING, SUMMER, AUTUMN, WINNER; } class Test{ public static void main(String[] args) { Season season = Season.SPRING; switch (season){ case SPRING: System.out.println(Season.SPRING); break; case SUMMER: System.out.println(Season.SUMMER); break; case AUTUMN: System.out.println(Season.AUTUMN); break; case WINNER: System.out.println(Season.WINNER); break; } } }
枚舉在switch中使用比較簡單,只需瞭解有這麼個狀況就OK了。
即然全部的枚舉類都是繼承自java.lang.Enum這個類,那麼每一個枚舉類都一定有可用的方法。咱們只例舉比較經常使用方法:
經常使用方法的舉例:
public enum Season { SPRING, SUMMER, AUTUMN, WINNER; } class Test{ public static void main(String[] args) { //Season.valueOf() Season season1 = Season.valueOf("SPRING"); System.out.println(season1); System.out.println("-------------"); //Season.values() Season[] values = Season.values(); for (Season season2:values){ System.out.println(season2); } System.out.println("-------------"); Season summer = Season.SUMMER; //name() System.out.println(summer.name()); //ordinal() System.out.println(summer.ordinal()); //toString() System.out.println(summer.toString()); } }
還有一些其餘的方法就不介紹了,有些應該都知道,而有些則不經常使用。有感興趣的話能夠本身去看看官方API或者源碼,都比較的簡單。
在前面的分析中,咱們都是基於簡單枚舉類型來定義的,並無在枚舉類中定義變量、方法、構造器等結構。實際上枚舉類和普通類有着相同的特徵,除了不能使用繼承以外(由於編譯器會自動爲咱們繼承Enum抽象類,而Java只支持單繼承),咱們徹底能夠把枚舉類當成普通類,下面咱們來感覺一下吧。
public enum Season { SPRING("春暖花開"), SUMMER("夏日炎炎"), AUTUMN("秋高氣爽"), WINNER("冬暖夏涼");//此時的分號不能省略 private String name; //系統默認構造器是private,並且必須是private的,用public則會報錯 Season(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Test{ public static void main(String[] args) { for (Season season:Season.values()){ System.out.println(season.name()+","+season.getName()); } } }
程序運行結果:
經過上述可知,雖然枚舉類中能夠普通類同樣聲明變量、成員方法、構造器。可是咱們必須注意到如下幾點:
①、枚舉類變量必須放在第一行,若是枚舉類變量有構造器,那麼分號必須加上,不然能夠省略。
②、枚舉類的構造器必須是private的,系統會自動設置爲private,咱們也能夠本身加上,可是不能用public等修飾符,不然會報錯。
枚舉類即然和普通類同樣,那麼枚舉類中就容許定義抽象類和接口,接口下一節講。可是須要注意的是每一個枚舉變量都須要重寫該方法,不然編譯會報錯。繼續用上面的例子,只是在其中添加了一個抽象方法。
public enum Season { SPRING("春暖花開"){ public String show(){ return "SPRING"; } }, SUMMER("夏日炎炎"){ public String show(){ return "SUMMER"; } }, AUTUMN("秋高氣爽"){ public String show(){ return "AUTUMN"; } }, WINNER("冬暖夏涼"){ public String show(){ return "WINNER"; } };//此時的分號不能省略 private String name; //系統默認構造器是private,並且必須是private的,用public則會報錯 Season(String name) { this.name = name; } //定義抽象方法 public abstract String show(); public String getName() { return name; } public void setName(String name) { this.name = name; } } class Test{ public static void main(String[] args) { for (Season season:Season.values()){ System.out.println(season.name()+","+season.getName()+",枚舉變量方法返回值:"+season.show()); } } }
程序運行結果:
經過這種方式就能夠垂手可得地定義每一個枚舉變量的不一樣行爲方式。並且調用枚舉變量中方法有兩種方式,一種是枚舉變量名稱.方法,另外一種是枚舉類名.枚舉變量.方法(如Season.SPRING.show());
雖然枚舉類不能再繼承其餘的類了,可是它仍是可以實現接口的,舉例:
interface Behaviour{ String show(); } public enum Season implements Behaviour{ SPRING("春暖花開"), SUMMER("夏日炎炎"), AUTUMN("秋高氣爽"), WINNER("冬暖夏涼");//此時的分號不能省略 private String name; //系統默認構造器是private,並且必須是private的,用public則會報錯 Season(String name) { this.name = name; } @Override public String show() { return this.name; } } class Test{ public static void main(String[] args) { for (Season season:Season.values()){ System.out.println(season.show()); } } }
這樣使用起來仍是比較的簡單的。在枚舉類中使用接口還有一個功能就是對一組數據進行分類,此時就能夠利用接口來組織枚舉。好比一年四季中包含的節氣:
public interface Season { enum Spring implements Season{ //立春,雨水,清明 SPRING_BEGINS,RAIN,TOMB_SWEEPING } enum Summer implements Season{ //夏至,芒種,小暑,大暑 SUMMER_BEGINS,GRAIN_INE_EAR,SLIGHT_HEAD,GREAT_HEAD } enum AUTUMN implements Season{ //立秋,寒露,霜降 AUTUMN_BEGINS,COLD_DEW,FROST } enum WINTER implements Season{ //立冬,小雪,大雪,冬至 WINTER_BEGINS,LIGHT_SNOW,HEAVY_SNOW,WINTER_SOLSTICE_FESTIVAL } } class Test{ public static void main(String[] args) { //遍歷Spring Season.Spring[] values = Season.Spring.values(); for (Season season:values){ System.out.println(season); } } } //運行結果: //SPRING_BEGINS //RAIN //TOMB_SWEEPING
經過上面這種方式咱們能夠很方便地組織枚舉,同時還確保了具體類型屬於春夏秋冬,而春夏秋冬則屬於季節Season。
EnumSet和EnumMap這兩個都是關於枚舉集合方面的知識,因此暫時不深刻學習,僅用示例來簡單瞭解一下。可是咱們要清楚一點EnumSet是保證集合中的元素不重複。而EnumMap中的 key是enum類型,而value則能夠是任意類型。
class Tests{ public static void main(String[] args) { // EnumSet的使用 EnumSet<Season> set=EnumSet.allOf(Season.class); System.out.println(set); for (Season season:set){ System.out.println(season); }// EnumMap的使用 EnumMap<Season,String> map=new EnumMap<Season, String>(Season.class); map.put(Season.SPRING,"春暖花開"); map.put(Season.SUMMER,"夏日炎炎"); map.put(Season.AUTUMN,"秋高氣爽"); map.put(Season.WINNER,"冬暖夏涼"); //遍歷map有不少種方式,這裏是map遍歷的一種方式,這種方式是最快的 for (EnumMap.Entry<Season,String> entry:map.entrySet()){ System.out.println(entry.getKey()+","+entry.getValue()); } } }
程序運行結果: