前言:
在第一次學習面向對象編程時,我記得最深的一句話就是“萬物皆對象”。於是我一直秉承着這個思想努力的學習着JAVA,直到學習到枚舉(Enum)時,看着它頗為奇怪的語法……我一直在想,這TM是個什么鬼???當時學習OOP時也是被類啊接口什么的整的有點昏頭轉向的於是就把這個小細節忽略掉了。后來到了公司工作后慢慢的又需要用上枚舉了,看着它一副神秘兮兮的樣子我還是決定要好好的深挖一下!以下鏈接是了解枚舉時所參考的博客。如發現本文有錯誤或知識遺漏歡迎在評論中指正!
反編譯那些事兒(二)—枚舉的反編譯:http://blog.csdn.net/gaohuanjie/article/details/18140279
JAVA枚舉與常量類的區別:http://blog.csdn.net/tanqian351/article/details/53736628
目錄:
1)歷史
2)語法解析
3)枚舉的好處以及與常量類的區別
4)枚舉常用方法
1.歷史:
枚舉是JDK1.5版本新增的特性(泛型、For-each等如今被廣泛應用的特性也是由JDK1.5時所新增的),另外到了JDK1.6后switch語句支持枚舉類型。
2.枚舉的語法解析:
1.最最最簡單版
public enum ColorEnum { RED,BLUE,GREEN }
通過工具解析class后獲得的源代碼(工具參考上面的鏈接)
public final class ColorEnum extends Enum { //返回存儲枚舉實例的數組的副本。values()方法通常用於foreach循環遍歷枚舉常量。 public static ColorEnum[] values() { return (ColorEnum[])$VALUES.clone(); } //根據實例名獲取實例 public static ColorEnum valueOf(String s) { return (ColorEnum)Enum.valueOf(ColorEnum, s); } //私有構造方法,這里調用了父類的構造方法,其中參數s對應了常量名,參數i代表枚舉的一個順序(這個順序與枚舉的聲明順序對應,用於oridinal()方法返回順序值) private ColorEnum(String s, int i) { super(s, i); } //我們定義的枚舉在這里聲明了三個 ColorEnum的常量對象引用,對象的實例化在static靜態塊中 public static final ColorEnum RED; public static final ColorEnum BLUE; public static final ColorEnum GREEN; //將所有枚舉的實例存放在數組中 private static final ColorEnum $VALUES[]; static { RED = new ColorEnum("RED", 0); BLUE = new ColorEnum("BLUE", 1); GREEN = new ColorEnum("GREEN", 2); //將所有枚舉的實例存放在數組中 $VALUES = (new ColorEnum[] { RED, BLUE, GREEN }); } }
2.現在我們在枚舉類中增加自己的字段以及一些輔助方法,代碼如下:
public enum ColorEnum { RED("red","紅色"),GREEN("green","綠色"),BLUE("blue","藍色"); //防止字段值被修改,增加的字段也統一final表示常量 private final String key; private final String value; private ColorEnum(String key,String value){ this.key = key; this.value = value; } //根據key獲取枚舉 public static ColorEnum getEnumByKey(String key){ if(null == key){ return null; } for(ColorEnum temp:ColorEnum.values()){ if(temp.getKey().equals(key)){ return temp; } } return null; } public String getKey() { return key; } public String getValue() { return value; } }
老規矩,反編譯看看變化?(其實也就看看static靜態塊和構造方法有什么變化就好了)
public final class ColorEnum extends Enum { public static ColorEnum[] values() { return (ColorEnum[])$VALUES.clone(); } public static ColorEnum valueOf(String s) { return (ColorEnum)Enum.valueOf(ColorEnum, s); } //構造方法在原基礎上加上我們新增的兩個形參 private ColorEnum(String s, int i, String s1, String s2) { super(s, i); key = s1; value = s2; } //自定義方法,通過key值獲得對應的枚舉對象 public static ColorEnum getEnumByKey(String s) { if(null == s) return null; ColorEnum acolorenum[] = values(); int i = acolorenum.length; for(int j = 0; j < i; j++) { ColorEnum colorenum = acolorenum[j]; if(colorenum.getKey().equals(s)) return colorenum; } return null; } public String getKey() { return key; } public String getValue() { return value; } public static final ColorEnum RED; public static final ColorEnum GREEN; public static final ColorEnum BLUE; //我們自定義的兩個字段 private final String key; private final String value; private static final ColorEnum $VALUES[]; static { RED = new ColorEnum("RED", 0, "red", "\u7EFE\u3223\u58CA"); GREEN = new ColorEnum("GREEN", 1, "green", "\u7F01\u80EF\u58CA"); BLUE = new ColorEnum("BLUE", 2, "blue", "\u9483\u6FCA\u58CA"); $VALUES = (new ColorEnum[] { RED, GREEN, BLUE }); } }
3.枚舉的好處以及與常量類的區別
1)枚舉型可以直接與數據庫打交道,我通常使用varchar類型存儲,對應的是枚舉的常量名。(數據庫中好像也有枚舉類型,不過也沒用過)
2) switch語句支持枚舉型,當switch使用int、String類型時,由於值的不穩定性往往會有越界的現象,對於這個的處理往往只能通過if條件篩選以及default模塊來處理。而使用枚舉型后,在編譯期間限定類型,不允許發生越界的情況
3) 當你使用常量類時,往往得通過equals去判斷兩者是否相等,使用枚舉的話由於常量值地址唯一,可以用==直接對比,性能會有提高
4) 常量類編譯時,是直接把常量的值編譯到類的二進制代碼里,常量的值在升級中變化后,需要重新編譯引用常量的類,因為里面存的是舊值。枚舉類編譯時,沒有把常量值編譯到代碼里,即使常量的值發生變化,也不會影響引用常量的類。
5)枚舉類編譯后默認為final class,不允許繼承可防止被子類修改。常量類可被繼承修改、增加字段等,容易導致父類的不兼容。
………………歡迎補充!
總結:常量的定義在開發中是必不可少的,雖然無論是通過常量類定義常量還是枚舉定義常量都可以滿足常量定義的需求。但個人建議最好是使用枚舉類型。
4.枚舉常用方法
1.values()獲取存儲枚舉中所有常量實例的數組。常配合foreach完成遍歷
for(ColorEnum temp:ColorEnum.values()){ System.out.println(temp); }
運行結果:
RED
GREEN
BLUE
2.構造方法,枚舉的構造方法只能用private修飾符修飾,原因就不需要解釋了……
3.valueOf()通過常量名獲取對應的枚舉實例。
ColorEnum red = ColorEnum.valueOf("RED");
System.out.println(red);