JAVA枚舉類型(Enum)的使用
在現實社會中,有些類的實例對象是固定的。例如季節,只有春夏秋冬。例如月份,只有1-12個月,如果你創建了一個月份類,你當然有義務維護這個類的實例對象只能12個。這個時候就體現出枚舉類的作用了,java中枚舉類型就是針對這樣的場景需求所設計的。
語法(定義)
創建枚舉類型要使用 enum 關鍵字,隱含了所創建的類型都是 java.lang.Enum 類的子類(java.lang.Enum 是一個抽象類)。枚舉類型符合通用模式 Class Enum<E extends Enum<E>>,而 E 表示枚舉類型的名稱。枚舉類型的每一個值都將映射到 protected Enum(String name, int ordinal) 構造函數中,在這裏,每個值的名稱都被轉換成一個字符串,並且序數設置表示了此設置被創建的順序。
使用MonthEnum這個枚舉類的方法如下:
創建MonthEnum枚舉類,在使用的時候利用switch語句進行匹配從而得到相應的輸出值,這種做法很常見。如果只需要實現這樣的功能,定義一個常量類也可以實現。那麼就讓我們更進一步來看看枚舉類的作用,針對上面的例子,如果我們在很多場景下都要通過MonthEnum的實例對象獲取相對應的中文,每次都使用switch語句就顯得代碼冗餘。開發中,我們可以通過創建MonthEnum這個枚舉類時,讓MonthEnum中的每一個實例對象都有一個getChineseDesc()方法獲取中文描述。
枚舉類限制了此類的實例對象。當然,枚舉類可以有自己的成員變量和方法。上面的MonthEnum枚舉類有了chineseDesc這個成員變量,所以我們在定義實例對象時就要維護這個chineseDesc成員變量。此時調用簡化代碼如下:
還有另外一種方式:
就是先定義一個接口,接口中定義獲取的方法。然後又枚舉類生聲明實現接口,並由具體枚舉類對象實現方法。
示例如下:
基類接口
子實現類-枚舉類
注意枚舉中所有的枚舉實例必須均實現接口方法。
調用方式如下:
我們把枚舉類的所有實例對象,看做是一個集合,上面的switch可以看做是一種集合的遍歷方式,當對象集size很大時,遍歷很繁瑣,極端不適合開發。
所以有下面的遍歷方式如下:
遍歷的順序是枚舉的實例對象聲明的順序。
上面的枚舉對象中使用的values的方法,下面介紹枚舉中的方法:
int
compareTo
(E o)
比較此枚舉與指定對象的順序。
Class<E> getDeclaringClass()
返回與此枚舉常量的枚舉類型相對應的 Class 對象。
String name()
返回此枚舉常量的名稱,在其枚舉聲明中對其進行聲明。
int ordinal()
返回枚舉常量的序數(它在枚舉聲明中的位置,其中初始常量序數爲零)。
String toString()
返回枚舉常量的名稱,它包含在聲明中。
static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
返回帶指定名稱的指定枚舉類型的枚舉常量。
給 enum 自定義屬性和方法
EnumSet,EnumMap 的應用
下面討論什麼場景使用枚舉類
當一個類的對象是存在且數量有限且固定的,這種情況下我們使用枚舉類就比較適當。
枚舉類更加直觀,類型安全。使用常量會有以下幾個缺陷:
1. 類型不安全。若一個方法中要求傳入季節這個參數,用常量的話,形參就是int類型,開發者傳入任意類型的int類型值就行,但是如果是枚舉類型的話,就只能傳入枚舉類中包含的對象。
2. 沒有命名空間。開發者要在命名的時候以SEASON_開頭,這樣另外一個開發者再看這段代碼的時候,才知道這四個常量分別代表季節。
三、枚舉類的語法及聲明注意事項
先看一個簡單的枚舉類。
1.enum和class、interface的地位一樣
2.使用enum定義的枚舉類默認繼承了java.lang.Enum,而不是繼承Object類。枚舉類可以實現一個或多個接口。
3.枚舉類的所有實例都必須放在第一行展示,不需使用new 關鍵字,不需顯式調用構造器。自動添加public static final修飾。
4.使用enum定義、非抽象的枚舉類默認使用final修飾,不可以被繼承。
5.枚舉類的構造器只能是私有的。
四.枚舉類介紹
枚舉類內也可以定義屬性和方法,可是是靜態的和非靜態的。
實際上在第一行寫枚舉類實例的時候,默認是調用了構造器的,所以此處需要傳入參數,因爲沒有顯式申明無參構造器,只能調用有參數的構造器。
構造器需定義成私有的,這樣就不能在別處申明此類的對象了。枚舉類通常應該設計成不可變類,它的Field不應該被改變,這樣會更安全,而且代碼更加簡潔。所以我們將Field用private final修飾。
五、枚舉類實現接口
枚舉類可以實現一個或多個接口。與普通類一樣,實現接口的時候需要實現接口中定義的所有方法,若沒有完全實現,那這個枚舉類就是抽象的,只是不需顯式加上abstract修飾,系統化會默認加上。