一:Enum 類型的介紹
枚舉類型(Enumerated Type) 很早就出現在編程語言中,它被用來將一組類似的值包含到一種類型當中。而這種枚舉類型的名稱則會被定義成獨一無二的類型描述符,在這一點上和常量的定義相似。不過相比較常量類型,枚舉類型可以為申明的變量提供更大的取值范圍。
二:Enum 類型的特點
- 在某些情況下,一個類的對象時有限且固定的,如季節類,它只有春夏秋冬4個對象這種實例有限且固定的類,在 Java 中被稱為枚舉類;
- 在 Java 中使用 enum 關鍵字來定義枚舉類,其地位與 class、interface 相同;
- 枚舉類是一種特殊的類,它和普通的類一樣,有自己的成員變量、成員方法、構造器 (只能使用 private 訪問修飾符,所以無法從外部調用構造器,構造器只在構造枚舉值時被調用);
- 一個 Java 源文件中最多只能有一個 public 類型的枚舉類,且該 Java 源文件的名字也必須和該枚舉類的類名相同,這點和類是相同的;
- 使用 enum 定義的枚舉類默認繼承了 java.lang.Enum 類,並實現了 java.lang.Seriablizable 和 java.lang.Comparable 兩個接口;
- 所有的枚舉值都是 public static final 的,且非抽象的枚舉類不能再派生子類;
- 枚舉類的所有實例(枚舉值)必須在枚舉類的第一行顯式地列出,否則這個枚舉類將永遠不能產生實例。列出這些實例(枚舉值)時,系統會自動添加 public static final 修飾,無需程序員顯式添加。
三:Enum 使用
1 package com.ljq.test; 2 3 /** 4 * 枚舉用法詳解 5 * 6 * @author jiqinlin 7 * 8 */ 9 public class TestEnum { 10 /** 11 * 普通枚舉 12 * 13 * @author jiqinlin 14 * 15 */ 16 public enum ColorEnum { 17 red, green, yellow, blue; 18 } 19 20 /** 21 * 枚舉像普通的類一樣可以添加屬性和方法,可以為它添加靜態和非靜態的屬性或方法 22 * 23 * @author jiqinlin 24 * 25 */ 26 public enum SeasonEnum { 27 //注:枚舉寫在最前面,否則編譯出錯 28 spring, summer, autumn, winter; 29 30 private final static String position = "test"; 31 32 public static SeasonEnum getSeason() { 33 if ("test".equals(position)) 34 return spring; 35 else 36 return winter; 37 } 38 } 39 40 /** 41 * 性別 42 * 43 * 實現帶有構造器的枚舉 44 * 45 * @author jiqinlin 46 * 47 */ 48 public enum Gender{ 49 //通過括號賦值,而且必須帶有一個參構造器和一個屬性跟方法,否則編譯出錯 50 //賦值必須都賦值或都不賦值,不能一部分賦值一部分不賦值;如果不賦值則不能寫構造器,賦值編譯也出錯 51 MAN("MAN"), WOMEN("WOMEN"); 52 53 private final String value; 54 55 //構造器默認也只能是private, 從而保證構造函數只能在內部使用 56 Gender(String value) { 57 this.value = value; 58 } 59 60 public String getValue() { 61 return value; 62 } 63 } 64 65 /** 66 * 訂單狀態 67 * 68 * 實現帶有抽象方法的枚舉 69 * 70 * @author jiqinlin 71 * 72 */ 73 public enum OrderState { 74 /** 已取消 */ 75 CANCEL {public String getName(){return "已取消";}}, 76 /** 待審核 */ 77 WAITCONFIRM {public String getName(){return "待審核";}}, 78 /** 等待付款 */ 79 WAITPAYMENT {public String getName(){return "等待付款";}}, 80 /** 正在配貨 */ 81 ADMEASUREPRODUCT {public String getName(){return "正在配貨";}}, 82 /** 等待發貨 */ 83 WAITDELIVER {public String getName(){return "等待發貨";}}, 84 /** 已發貨 */ 85 DELIVERED {public String getName(){return "已發貨";}}, 86 /** 已收貨 */ 87 RECEIVED {public String getName(){return "已收貨";}}; 88 89 public abstract String getName(); 90 } 91 92 public static void main(String[] args) { 93 //枚舉是一種類型,用於定義變量,以限制變量的賦值;賦值時通過“枚舉名.值”取得枚舉中的值 94 ColorEnum colorEnum = ColorEnum.blue; 95 switch (colorEnum) { 96 case red: 97 System.out.println("color is red"); 98 break; 99 case green: 100 System.out.println("color is green"); 101 break; 102 case yellow: 103 System.out.println("color is yellow"); 104 break; 105 case blue: 106 System.out.println("color is blue"); 107 break; 108 } 109 110 //遍歷枚舉 111 System.out.println("遍歷ColorEnum枚舉中的值"); 112 for(ColorEnum color : ColorEnum.values()){ 113 System.out.println(color); 114 } 115 116 //獲取枚舉的個數 117 System.out.println("ColorEnum枚舉中的值有"+ColorEnum.values().length+"個"); 118 119 //獲取枚舉的索引位置,默認從0開始 120 System.out.println(ColorEnum.red.ordinal());//0 121 System.out.println(ColorEnum.green.ordinal());//1 122 System.out.println(ColorEnum.yellow.ordinal());//2 123 System.out.println(ColorEnum.blue.ordinal());//3 124 125 //枚舉默認實現了java.lang.Comparable接口 126 System.out.println(ColorEnum.red.compareTo(ColorEnum.green));//-1 127 128 //-------------------------- 129 System.out.println("==========="); 130 System.err.println("季節為" + SeasonEnum.getSeason()); 131 132 133 //-------------- 134 System.out.println("==========="); 135 for(Gender gender : Gender.values()){ 136 System.out.println(gender.value); 137 } 138 139 //-------------- 140 System.out.println("==========="); 141 for(OrderState order : OrderState.values()){ 142 System.out.println(order.getName()); 143 } 144 } 145 146 }
四:枚舉集合的使用
java.util.EnumSet和java.util.EnumMap是兩個枚舉集合。EnumSet保證集合中的元素不重復;EnumMap中的 key是enum類型,而value則可以是任意類型
JDK5.0 中在增加 Enum 類的同時,也增加了兩個工具類 EnumSet 和 EnumMap,這兩個類都放在 java.util 包中。EnumSet 是一個針對枚舉類型的高性能的 Set 接口實現。EnumSet 中裝入的所有枚舉對象都必須是同一種類型,在其內部,是通過 bit-vector 來實現,也就是通過一個 long 型數。EnumSet 支持在枚舉類型的所有值的某個范圍中進行迭代。
1
|
enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun }
|
你能夠在每周七天日期中進行迭代,EnumSet 類提供一個靜態方法 range 讓迭代很容易完成:
1
2
3
|
for(WeekDayEnum day : EnumSet.range(WeekDayEnum.Mon, WeekDayEnum.Fri)) {
System.out.println(day);
}
|
打印結果如下:
1
2
3
4
5
|
Mon
Tue
Wed
Thu
Fri
|
EnumSet 還提供了很多個類型安全的獲取子集的 of 方法,很容易取得子集:
1
2
3
4
|
EnumSet<
WeekDayEnum
> subset = EnumSet.of(WeekDayEnum.Mon, WeekDayEnum.Wed);
for (WeekDayEnum day : subset) {
System.out.println(day);
}
|
打印結果如下:
1
2
|
Mon
Wed
|
與 EnumSet 類似,EnumMap 也是一個高性能的 Map 接口實現,用來管理使用枚舉類型作為 keys 的映射表,內部是通過數組方式來實現。EnumMap 將豐富的和安全的 Map 接口與數組快速訪問結合到一起,如果你希望要將一個枚舉類型映射到一個值,你應該使用 EnumMap。看下面的例子:
1
2
3
4
5
6
7
8
9
10
11
12
|
// 定義一個 EnumMap 對象,映射表主鍵是日期枚舉類型,值是顏色枚舉類型
private static Map<
WeekDayEnum
, RainbowColor> schema =
new EnumMap<
WeekDayEnum
, RainbowColor>(WeekDayEnum.class);
static{
// 將一周的每一天與彩虹的某一種色彩映射起來
for (int i = 0; i < WeekDayEnum.values().length; i++) {
schema.put(WeekDayEnum.values()[i], RainbowColor.values()[i]);
}
}
System.out.println("What is the lucky color today?");
System.out.println("It's " + schema.get(WeekDayEnum.Sat));
|