一、理解枚舉類型
枚舉類型是Java 5中新增特性的一部分,它是一種特殊的數據類型,之所以特殊是因為它既是一種類(class)類型卻又比類類型多了些特殊的約束,但是這些約束的存在也造就了枚舉類型的簡潔性、安全性以及便捷性。下面先來看看如何寫一個枚舉?
二、枚舉的定義語法
在沒有枚舉類型時定義常量常見的方式
上述的常量定義常量的方式稱為int枚舉模式,這樣的定義方式並沒有什么錯,但它存在許多不足,如在類型安全和使用方便性上並沒有多少好處,如果存在定義int值相同的變量,容易混淆,因此這種方式在枚舉出現后並不提倡,現在我們利用枚舉類型來重新定義上述的常量,定義周一到周日的常量
//枚舉類型,使用關鍵字enum
相當簡潔,在定義枚舉類型時我們使用的關鍵字是enum,與class關鍵字類似,只不過前者是定義枚舉類型,后者是定義類類型。
枚舉類型Day中分別定義了從周一到周日的值,這里要注意,值一般是大寫的字母,多個值之間以逗號分隔。同時我們應該知道的是枚舉類型可以像類(class)類型一樣,定義為一個單獨的文件,當然也可以定義在其他類內部,更重要的是枚舉常量在類型安全性和便捷性都很有保證,如果出現類型問題編譯器也會提示我們改進,但務必記住枚舉表示的類型其取值是必須有限的,也就是說每個值都是可以枚舉出來的,比如上述描述的一周共有七天。
以上是寫法,寫好后該如何使用呢?如下:
就像上述代碼那樣,直接引用枚舉的值即可,這便是枚舉類型的最簡單模型。
三、為什么可以這樣用,看看枚舉實現原理就知道了
我們大概了解了枚舉類型的定義與簡單使用后,現在有必要來了解一下枚舉類型的基本實現原理。實際上在使用關鍵字enum創建枚舉類型並編譯后,編譯器會為我們生成一個相關的類,這個類繼承了Java API中的java.lang.Enum類,也就是說通過關鍵字enum創建枚舉類型在編譯后事實上也是一個類類型而且該類繼承自java.lang.Enum類。我們可以看看反編譯的結果!
結論:從反編譯的代碼可以看出編譯器確實幫助我們生成了一個Day類而且該類繼承自java.lang.Enum類,該類是一個抽象類,除此之外,編譯器還幫助我們生成了7個Day類型的實例對象分別對應枚舉中定義的7個日期。還為我們生成了兩個靜態方法,分別是values()和 valueOf(),到此我們也就明白了,使用關鍵字enum定義的枚舉類型,在編譯期后,也將轉換成為一個實實在在的類,而在該類中,會存在每個在枚舉類型中定義好常量的對應實例對象,如上述的MONDAY枚舉類型對應public static final Day MONDAY;
四、編譯器生成的Values方法與ValueOf方法
values()方法和valueOf(String name)方法是編譯器生成的static方法,后面我們自己定義的枚舉類的父類Enum的分析中,在Enum類中並沒出現values()方法,但valueOf()方法還是有出現的,只不過編譯器生成的valueOf()方法需傳遞一個name參數,而Enum自帶的靜態方法valueOf()則需要傳遞兩個方法,從前面反編譯后的代碼可以看出,編譯器生成的valueOf方法最終還是調用了Enum類的valueOf方法,下面通過代碼來演示這兩個方法的作用:
輸出結果:
從結果可知道,values()方法的作用就是獲取枚舉類中的所有變量,並作為數組返回,而valueOf(String name)方法與Enum類中的valueOf方法的作用類似根據名稱獲取枚舉變量,只不過編譯器生成的valueOf方法更簡潔些只需傳遞一個參數。
五、Enum抽象類常見方法
Enum是所有 Java 語言枚舉類型的公共基本類(注意Enum是抽象類),以下是它的常見方法:
ordinal()方法,該方法獲取的是枚舉變量在枚舉類中聲明的順序,下標從0開始,如日期中的MONDAY在第一個位置,那么MONDAY的ordinal值就是0,如果MONDAY的聲明位置發生變化,那么ordinal方法獲取到的值也隨之變化,注意在大多數情況下我們都不應該首先使用該方法,畢竟它總是變幻莫測的。
compareTo(E o)方法則是比較枚舉的大小,注意其內部實現是根據每個枚舉的ordinal值大小進行比較的。
name()方法與toString()幾乎是等同的,都是輸出變量的字符串形式。
valueOf(Class enumType, String name)方法則是根據枚舉類的Class對象和枚舉名稱獲取枚舉常量,注意該方法是靜態的。
下面的代碼演示了上述方法:
六、枚舉的進階用法
向enum類添加方法與自定義屬性和構造函數 重新定義一個日期枚舉類,帶有desc成員變量描述該日期的對於中文描述,同時定義一個getDesc方法,返回中文描述內容,自定義私有構造函數,在聲明枚舉實例時傳入對應的中文描述,代碼如下:
輸出結果:
————————————————
版權聲明:本文為CSDN博主「奮斗的哼哼」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43610698/article/details/90737759
一、理解枚舉類型枚舉類型是Java 5中新增特性的一部分,它是一種特殊的數據類型,之所以特殊是因為它既是一種類(class)類型卻又比類類型多了些特殊的約束,但是這些約束的存在也造就了枚舉類型的簡潔性、安全性以及便捷性。下面先來看看如何寫一個枚舉?二、枚舉的定義語法在沒有枚舉類型時定義常量常見的方式 public class DayDemo { public static final int MONDAY =1; public static final int TUESDAY=2; public static final int WEDNESDAY=3; public static final int THURSDAY=4; public static final int FRIDAY=5; public static final int SATURDAY=6; public static final int SUNDAY=7; }123456789上述的常量定義常量的方式稱為int枚舉模式,這樣的定義方式並沒有什么錯,但它存在許多不足,如在類型安全和使用方便性上並沒有多少好處,如果存在定義int值相同的變量,容易混淆,因此這種方式在枚舉出現后並不提倡,現在我們利用枚舉類型來重新定義上述的常量,定義周一到周日的常量//枚舉類型,使用關鍵字enum
enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }1234相當簡潔,在定義枚舉類型時我們使用的關鍵字是enum,與class關鍵字類似,只不過前者是定義枚舉類型,后者是定義類類型。
枚舉類型Day中分別定義了從周一到周日的值,這里要注意,值一般是大寫的字母,多個值之間以逗號分隔。同時我們應該知道的是枚舉類型可以像類(class)類型一樣,定義為一個單獨的文件,當然也可以定義在其他類內部,更重要的是枚舉常量在類型安全性和便捷性都很有保證,如果出現類型問題編譯器也會提示我們改進,但務必記住枚舉表示的類型其取值是必須有限的,也就是說每個值都是可以枚舉出來的,比如上述描述的一周共有七天。
以上是寫法,寫好后該如何使用呢?如下:
public class EnumDemo { public static void main(String[] args){ //直接引用 Day day =Day.MONDAY; } }123456就像上述代碼那樣,直接引用枚舉的值即可,這便是枚舉類型的最簡單模型。
三、為什么可以這樣用,看看枚舉實現原理就知道了我們大概了解了枚舉類型的定義與簡單使用后,現在有必要來了解一下枚舉類型的基本實現原理。實際上在使用關鍵字enum創建枚舉類型並編譯后,編譯器會為我們生成一個相關的類,這個類繼承了Java API中的java.lang.Enum類,也就是說通過關鍵字enum創建枚舉類型在編譯后事實上也是一個類類型而且該類繼承自java.lang.Enum類。我們可以看看反編譯的結果!結論:從反編譯的代碼可以看出編譯器確實幫助我們生成了一個Day類而且該類繼承自java.lang.Enum類,該類是一個抽象類,除此之外,編譯器還幫助我們生成了7個Day類型的實例對象分別對應枚舉中定義的7個日期。還為我們生成了兩個靜態方法,分別是values()和 valueOf(),到此我們也就明白了,使用關鍵字enum定義的枚舉類型,在編譯期后,也將轉換成為一個實實在在的類,而在該類中,會存在每個在枚舉類型中定義好常量的對應實例對象,如上述的MONDAY枚舉類型對應public static final Day MONDAY;
四、編譯器生成的Values方法與ValueOf方法values()方法和valueOf(String name)方法是編譯器生成的static方法,后面我們自己定義的枚舉類的父類Enum的分析中,在Enum類中並沒出現values()方法,但valueOf()方法還是有出現的,只不過編譯器生成的valueOf()方法需傳遞一個name參數,而Enum自帶的靜態方法valueOf()則需要傳遞兩個方法,從前面反編譯后的代碼可以看出,編譯器生成的valueOf方法最終還是調用了Enum類的valueOf方法,下面通過代碼來演示這兩個方法的作用: Day[] days2 = Day.values(); System.out.println("day2:"+Arrays.toString(days2)); Day day = Day.valueOf("MONDAY"); System.out.println("day:"+day);1234輸出結果:
day2:[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY] day:MONDAY12從結果可知道,values()方法的作用就是獲取枚舉類中的所有變量,並作為數組返回,而valueOf(String name)方法與Enum類中的valueOf方法的作用類似根據名稱獲取枚舉變量,只不過編譯器生成的valueOf方法更簡潔些只需傳遞一個參數。
五、Enum抽象類常見方法Enum是所有 Java 語言枚舉類型的公共基本類(注意Enum是抽象類),以下是它的常見方法:
ordinal()方法,該方法獲取的是枚舉變量在枚舉類中聲明的順序,下標從0開始,如日期中的MONDAY在第一個位置,那么MONDAY的ordinal值就是0,如果MONDAY的聲明位置發生變化,那么ordinal方法獲取到的值也隨之變化,注意在大多數情況下我們都不應該首先使用該方法,畢竟它總是變幻莫測的。
compareTo(E o)方法則是比較枚舉的大小,注意其內部實現是根據每個枚舉的ordinal值大小進行比較的。
name()方法與toString()幾乎是等同的,都是輸出變量的字符串形式。
valueOf(Class enumType, String name)方法則是根據枚舉類的Class對象和枚舉名稱獲取枚舉常量,注意該方法是靜態的。
下面的代碼演示了上述方法:
public class EnumDemo { public static void main(String[] args){ //創建枚舉數組 Day[] days=new Day[]{Day.MONDAY, Day.TUESDAY, Day.WEDNESDAY, Day.THURSDAY, Day.FRIDAY, Day.SATURDAY, Day.SUNDAY}; for (int i = 0; i <days.length ; i++) { System.out.println("day["+i+"].ordinal():"+days[i].ordinal()); }
System.out.println("-------------------------------------"); //通過compareTo方法比較,實際上其內部是通過ordinal()值比較的 System.out.println("days[0].compareTo(days[1]):"+days[0].compareTo(days[1])); System.out.println("days[0].compareTo(days[1]):"+days[0].compareTo(days[2]));
//獲取該枚舉對象的Class對象引用,當然也可以通過getClass方法 Class<?> clazz = days[0].getDeclaringClass(); System.out.println("clazz:"+clazz);
System.out.println("-------------------------------------");
//name() System.out.println("days[0].name():"+days[0].name()); System.out.println("days[1].name():"+days[1].name());
System.out.println("-------------------------------------");
System.out.println("days[0].toString():"+days[0].toString()); System.out.println("days[1].toString():"+days[1].toString()); System.out.println("-------------------------------------");
Day d=Enum.valueOf(Day.class,days[0].name()); Day d2=Day.valueOf(Day.class,days[0].name()); System.out.println("d:"+d); System.out.println("d2:"+d2); }123456789101112131415161718192021222324252627282930313233343536六、枚舉的進階用法向enum類添加方法與自定義屬性和構造函數 重新定義一個日期枚舉類,帶有desc成員變量描述該日期的對於中文描述,同時定義一個getDesc方法,返回中文描述內容,自定義私有構造函數,在聲明枚舉實例時傳入對應的中文描述,代碼如下: public enum Day2 { MONDAY("星期一",1), TUESDAY("星期二",2), WEDNESDAY("星期三",3), THURSDAY("星期四",4), FRIDAY("星期五",5), SATURDAY("星期六",6), SUNDAY("星期日",7);//記住要用分號結束
private String desc;//文字描述 private Integer code; //對應的代碼
/** * 私有構造,防止被外部調用 * @param desc */ private Day2(String desc,Integer code){ this.desc=desc; this.code=code; } /** * 定義方法,返回描述,跟常規類的定義沒區別 * @return */ public String getDesc(){ return desc; }
/** * 定義方法,返回代碼,跟常規類的定義沒區別 * @return */ public String getCode(){ return code; } public static void main(String[] args){ for (Day2 day:Day2.values()) { System.out.println("name:"+day.name()+ ",desc:"+day.getDesc()); } }1234567891011121314151617181920212223242526272829303132333435363738394041輸出結果:
name:MONDAY,desc:星期一 name:TUESDAY,desc:星期二 name:WEDNESDAY,desc:星期三 name:THURSDAY,desc:星期四 name:FRIDAY,desc:星期五 name:SATURDAY,desc:星期六 name:SUNDAY,desc:星期日————————————————版權聲明:本文為CSDN博主「奮斗的哼哼」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/weixin_43610698/article/details/90737759