Java——枚舉:優雅而干凈的enum


Java編程思想》中有這么一句話:“有時恰恰因為它,你才能夠‘優雅而干凈’地解決問題”——這句話說的是誰呢?就是本篇的主角——枚舉(Enum)——大家鼓掌了。

在之前很長時間一段時間里,我都不怎么用枚舉,因為總感覺它沒什么用處——這其實就是“自我認知”的短見。當一個人一直蹲在自己的深井里而不敢跳出來的話,那他真的只能看到井口那么大點的天空。

隨著時間的推移,我做的項目越來越多,和枚舉見面的機會也越來越多,于是我就漸漸地對它越來越有興趣,研究得多了,才發現原來枚舉如此的優秀。

一、枚舉的常規用法

一個精簡的枚舉非常的干凈優雅,見下例。



我們為沉默枚舉創建了三個值,分別是王二、王三、王四。這段代碼實際上調用了3次Enum(String name, int ordinal)(ordinal單詞的意思為順序),也就是:



我們來遍歷輸出一下枚舉:



二、作為switch的判斷條件

使用枚舉作為switch語句判斷條件能讓我們的代碼可讀性更強,示例如下。



在通過case關鍵字判斷的時候,可以直接使用枚舉值,非常簡潔。另外,在編譯期間限定類型,可以有效的避免越界的情況——字符串常量類型在作為switch判斷條件的時候很容易因為誤寫而發生越界問題。

三、枚舉實現單例

《Effective Java》一書中對使用枚舉實現單例的方式推崇備至:



我覺得“雖然還沒有廣泛采用”幾個字可以去掉了,時至今日,大家應該都知道:使用枚舉實現單例是一種非常好的方式。

先來看“雙重校驗鎖”實現的單例:



再來看枚舉實現的單例:



不比不知道,一比嚇一跳啊!枚舉方式的單例簡單到爆——為了不至于看起來太過精簡,我還加了一個輸出“我很快樂”的方法。

枚舉實現的單例可輕松地解決兩個問題:

線程安全問題。因為Java虛擬機在加載枚舉類的時候,會使用ClassLoader的loadClass方法,這個方法使用了同步代碼塊來保證線程安全。

避免反序列化破壞單例。因為枚舉的反序列化并不通過反射實現。


四、枚舉可與數據庫交互

我們可以配合Mybatis將數據庫字段轉換為枚舉類型。現在假設有一個數據庫字段check_type的類型如下:



它對應的枚舉類型為CheckType,代碼如下:



CheckType枚舉類比我們剛開始見到的那個Chenmo枚舉類要復雜一些。

第一,CheckType新添加了構造方法,還有兩個字段,key為int型,text為String型。

第二,CheckType中有一個public static CheckType parse(Integer index)方法,可將一個Integer通過key的匹配轉化為枚舉類型。

那么現在,我們可以在Mybatis的配置文件中使用typeHandler將數據庫字段轉化為枚舉類型。



其中checkType字段對應的類如下:



CheckTypeHandler轉換器的類源碼如下:



CheckTypeHandler 的核心功能就是調用CheckType枚舉類的parse()方法對數據庫字段進行轉換。

五、枚舉會比靜態常量更消耗內存嗎?

說完枚舉最常用的4個知識點后,我們來討論一下“枚舉會比靜態常量更消耗內存嗎?”這個話題——簡書上有人問這樣的問題,還有很多人參與回答。

按我的理解,問這個問題的人就好像是在問“0.000,001”比“0.000,000,99”大嗎?你說是嗎?

寫在最后

歡迎加入java互聯網架構Q群:815220368,進群可免費領取資料和解答

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容