枚舉
枚舉是一個小功能,但是卻帶來了大方便。一個星期有七天,我們平時定義這七天為常量的時候,會這么寫:
public final static String SUNDAY = "0"; public final static String MONDAY = "1"; public final static String TUESDAY = "2"; public final static String WEDNESDAY = "3"; public final static String THRUSDAY = "4"; public final static String FRIDAY = "5"; public final static String SATURDAY = "6";
有了枚舉之后,就可以換一種寫法了:
public enum EnumDay { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THRUSDAY, FRIDAY, SATURDAY; }
這就定義了SUNDAY~SATURDAY的枚舉了,使用枚舉類型代替了常量,還提供了比常量更多的方法。枚舉類型適用的數據有以下特點:
1、枚舉值之間是有內在關聯的,比如上面的,都是一個星期的七天
2、常量的值是隨便的,比如SUNDAY必須是"12345",MONDAY必須是"23456"也可以用枚舉,不過要麻煩些
上面的EnumDay其實隱含了所創建的類型都是java.lang.Enum類的子類,枚舉類型符合通用模式Class Enum<E extends Enum<E>>,E表示的就是枚舉類型的名稱。枚舉類型的每一個值都將映射到protected Enum<String name, int ordinal>構造函數中,在這里,每個值的名稱都被轉換為一個字符串,並且序數設置表示了此設置被創建的順序。EnumDay實際調用了7此Enum:
new Enum<EnumDay>("SUNDAY", 0); new Enum<EnumDay>("MONDAY", 1); new Enum<EnumDay>("TUESDAY", 2); new Enum<EnumDay>("WEDNESDAY", 3); new Enum<EnumDay>("THRUSDAY", 4); new Enum<EnumDay>("FRIDAY", 5); new Enum<EnumDay>("SATURDAY", 6);
所以,只要記住每個枚舉值都是一個泛型為EnumDay的Enum就可以了。
遍歷枚舉類型及枚舉方法
既然知道了枚舉類型里面的枚舉值都是一個Enum<EnumDay>,那就好辦了,可以查看JDK API來看下Enum里面有哪些方法並使用下,看一下例子:
public static void main(String[] args) throws Exception { EnumDay[] eds = EnumDay.values(); // 將EnumDay中的枚舉值轉換為EnumDay數組 int i = 0; for (EnumDay ed : eds) { System.out.println("EnumDay[" + i + "]:" + ed.toString()); // 返回枚舉常量的名稱 i++; } System.out.println(); System.out.println("Enum<EnumDay>.compareTo():" + eds[0].compareTo(eds[1])); // 比較此枚舉與指定枚舉的順序,被比較對象小於、等於、大於比較對象時,分別返回負整數、0、正整數,只能和相同枚舉類型相比較 System.out.println("Enum<EnumDay>.equals():" + eds[0].equals(eds[1])); // 比較指定兩個枚舉類型是否相同 System.out.println("Enum<EnumDay>.getDeclaringClass():" + eds[0].getDeclaringClass()); // 獲取指定枚舉值的枚舉類型對應的Class對象 System.out.println("Enum<EnumDay>.hashCode():" + eds[0].hashCode()); // 獲取指定枚舉值對應的hashCode System.out.println("Enum<EnumDay>.name():" + eds[0].name()); // 獲取指定枚舉值的名稱 System.out.println("Enum<EnumDay>.ordinal():" + eds[0].ordinal()); // 獲取指定枚舉值對應的序數 }
結果為:
EnumDay[0]:SUNDAY EnumDay[1]:MONDAY EnumDay[2]:TUESDAY EnumDay[3]:WEDNESDAY EnumDay[4]:THRUSDAY EnumDay[5]:FRIDAY EnumDay[6]:SATURDAY Enum<EnumDay>.compareTo():-1 Enum<EnumDay>.equals():false Enum<EnumDay>.getDeclaringClass():class com.xrq.test37.EnumDay Enum<EnumDay>.hashCode():1414159026 Enum<EnumDay>.name():SUNDAY Enum<EnumDay>.ordinal():0
看到toString()方法和name()方法的值是一樣,可能有人會想,那要這兩個方法干嘛?toString()方法這里因為沒有重寫,實際上這個方法被開發者重寫之后,就打印出了開發者需要的內容了,沒有重寫toString()方法打印的就是name屬性了,看一下Enum類的源代碼就知道了。
為枚舉類型中的枚舉值定義數值----自定義屬性和方法
不給枚舉類型中的枚舉值定義數值,那么數值是從0開始逐個加上去的,當然我們也可以給枚舉類型中的枚舉值自定義數值,這時就要在EnumDay里面自定義屬性和方法了:
public enum EnumDay { SUNDAY(1234), MONDAY(2345), TUESDAY(3456), WEDNESDAY(4567), THRUSDAY(5678), FRIDAY(6789), SATURDAY(7890) { public String toString() { return super.toString(); } }; private int value; private EnumDay(int value) { this.value = value; } public int getValue() { return value; } }
main函數可以直接調用getValue()方法,因為每個枚舉值都是一個EnumDay:
public static void main(String[] args) { EnumDay[] eds = EnumDay.values(); for (EnumDay ed : eds) { System.out.println(ed.name() + ":" + ed.getValue()); } }
運行結果為:
SUNDAY:1234 MONDAY:2345 TUESDAY:3456 WEDNESDAY:4567 THRUSDAY:5678 FRIDAY:6789 SATURDAY:7890
從例子中看到,可以為枚舉類型自定義方法,也可以自定義屬性,也可以重寫父類中的方法(如果不自定義方法的話,只有toString()方法可以重寫,因為只有它不是final的),枚舉類型是Enum<E extends Enum<E>>,所以EnumDay也可以繼承類,實現接口,定義更多的方法。
EnumSet、EnumMap
EnumSet和EnumMap是分別為枚舉類型定制的Set和Map,看一下它們的用法:
public static void main(String[] args) { EnumSet<EnumDay> es = EnumSet.allOf(EnumDay.class); for (EnumDay ed : es) System.out.println(ed.name() + ":" + ed.ordinal()); System.out.println("\n-----EnumSet和EnumMap之間的分隔線-----\n"); EnumMap<EnumDay, String> em = new EnumMap<EnumDay, String>(EnumDay.class); em.put(EnumDay.SUNDAY, "星期天"); em.put(EnumDay.MONDAY, "星期一"); em.put(EnumDay.TUESDAY, "星期二"); em.put(EnumDay.WEDNESDAY, "星期三"); em.put(EnumDay.THRUSDAY, "星期四"); em.put(EnumDay.FRIDAY, "星期五"); em.put(EnumDay.SATURDAY, "星期六"); Iterator<Entry<EnumDay, String>> iterator = em.entrySet().iterator(); while (iterator.hasNext()) { Entry<EnumDay, String> entry = iterator.next(); System.out.println(entry.getKey().name() + ":" + entry.getValue()); } }
運行結果為:
SUNDAY:0 MONDAY:1 TUESDAY:2 WEDNESDAY:3 THRUSDAY:4 FRIDAY:5 SATURDAY:6 -----EnumSet和EnumMap之間的分隔線----- SUNDAY:星期天 MONDAY:星期一 TUESDAY:星期二 WEDNESDAY:星期三 THRUSDAY:星期四 FRIDAY:星期五 SATURDAY:星期六
注意一下EnumSet和EnumMap都是線程非安全的。