一、什麼是列舉?
首先,列舉是一種特殊的類物件,其定義如下:
{修飾符} enum 物件標識 [父介面] 列舉體
列舉型別通過一些特殊的約束,來實現其應用特性:
1、列舉不可定義為abstract 或者 final,否則會引發編譯器錯誤。
2、列舉實現了Comparable及Serializable介面,因此可以進行比較及序列化等操作,型別定義如下:
3、列舉型別只能通過內部的列舉常量進行初始化
4、列舉型別clone方法定義為final,即不可複製,否則會丟擲異常:
5、列舉型別無法通過反射機制進行初始化。
6、列舉型別需要自定義處理序列化,反序列化,預設的序列化使用會丟擲異常。
7、列舉型別equals定義為final,不可自定義覆蓋,同關聯hashCode方法。
8、列舉型別finalize定義為final,意味著列舉例項可能永遠不會被垃圾回收。
二、列舉的初始化
如下圖,我們定義EnvEnum型別列舉,然後通過PROD、RELEASE、DEV列舉常量初始化了三個EnvEnum例項:
列舉常量體可以包含引數,引數會通過建構函式進行列舉型別的初始化。
列舉體相當於定義了一個內部匿名類,但是不可包含建構函式及abstract方法。
列舉型別的建構函式有以下特殊約定限制:
1、建構函式預設為private修飾(不可外部初始化構造),不可使用public 或者 protected修飾,否則會導致編譯錯誤。
2、不可在建構函式內呼叫父類建構函式。
3、列舉型別會預設宣告無參建構函式。
三、列舉的一些特性
1、valueOf:根據列舉常量名稱查詢列舉例項。
列舉型別提供根據名稱查詢例項方法,需要注意的是,如果查詢不到匹配的例項,則會丟擲異常。
2、compareTo:提供列舉例項對比方法
對比需要再同型別列舉例項間,根據列舉例項的ordinal對比實現。
四、關於使用列舉、常量
其實,很多情況下,列舉和常量可以替代使用,對於第二部分 EnvEnum 示例,我們可以定義常量類如下:
但是,在實際應用中,在不同情景下的使用便捷性及程式碼複雜度上,卻有著不小的區別:
1、對比、查詢
當需要做同型別對比,查詢類操作時,常量類需要對相應的常量組定義,實現相應的功能方法。
可預知的是在實際應用中,會有很多不同型別組常量應用需求,那麼各組變數的對比,查詢則需要分別去實現,而列舉相應的功能囊括在列舉型別定義中,可以直接使用。
2、關聯性的使用
本篇中,我們定義了不同環境的(appId、appPort)配置使用,即,在使用PROD環境配置的appId時,同時可能會使用其appPort。在不同應用情景中,可能存在更多特性配置的關聯使用,這就很可能造成使用中的關聯性、匹配性的麻煩和混亂。比如,不小心組合使用了PROD_APP_ID和RELEASE_APP_PORT兩個變數。
列舉例項將所有的關聯特性包裝在一起,更適合此種情景應用,如:(EnvEnum.PROD.getAppId()、EnvEnum.PROD.getAppPort())
總的來說,常量更適用於單一或者單一組合的全域性性應用,而列舉更適合多組合多屬性關聯的複雜情景應用。
當然,我們這裡只是說適合,不是必需。