枚举类型enum用法_Java枚举深度解读,看这篇就够了
作者 | 濤GuoGuo的跟屁蟲丶博Ke
來(lái)源 | urlify.cn/aaamQf
66套java從入門到精通實(shí)戰(zhàn)課程分享
Java枚舉
1、枚舉類概念的理解與定義
- 一個(gè)類的對(duì)象是有限個(gè),確定的,我們稱此為枚舉類。
- 當(dāng)需要定義和維護(hù)一組常量時(shí),強(qiáng)烈建議使用枚舉類。
- 如果一個(gè)枚舉類中只有一個(gè)對(duì)象,則可以作為單例模式的實(shí)現(xiàn)方式。
2、枚舉類的定義
關(guān)于枚舉類的定義,這塊主要想和大家分享兩種方式
3、實(shí)踐
(一)、準(zhǔn)備工作
我們新建一個(gè) Java Project ,并創(chuàng)建一個(gè)包,以及一個(gè)測(cè)試類
(二)、自定義枚舉的三種方式(jdk 5.0 之前)
1. 定義一個(gè)抽象類,在抽象類中定義常量進(jìn)行維護(hù),我們接下來(lái)以 Java 類庫(kù)中的 Calendar 類示例來(lái)進(jìn)行說明
新建一個(gè)類 EnumDemo01.java 代碼如下:
package?org.taoguoguo;import?java.util.Calendar;/**?*?@author?taoGG?*?@description?jdk?5.0?之前?抽象類枚舉方案Demo?*?@create?2020-09-13?14:20?*/public?class?EnumDemo01?{????public?static?void?main(String[]?args)?{????????Calendar?calendar?=?Calendar.getInstance();????????System.out.println(calendar.get(1));????}}Console 結(jié)果輸出:
2020Process?finished?with?exit?code?0如果熟悉 Calendar API 的小伙伴 應(yīng)該馬上能反應(yīng)過來(lái),這個(gè)是獲取當(dāng)前的年份,類似的值還有
3?-?一年中的第幾個(gè)星期4?-?一年中的第幾個(gè)月5?-?當(dāng)前的日期?......但是這么多值,我們?cè)趺茨苡浀米∧?#xff1f;萬(wàn)一我輸入錯(cuò)誤,隨便取了一個(gè)范圍怎么辦?
沒錯(cuò),這是 jdk 5.0之前的痛點(diǎn),為了解決實(shí)例數(shù)量固定,便于維護(hù)這些問題,在jdk 5.0之后更新Enum枚舉類解決了這個(gè)問題。那在jdk 5.0之前官方是怎么做的呢?難道需要我們一個(gè)個(gè)去記住 Calendar 的數(shù)字?
實(shí)際上官方本身,采用的就是我們現(xiàn)在說的第一種方式,在抽象類中定義常量進(jìn)行維護(hù)
現(xiàn)在我們將代碼做些修改:
package?org.taoguoguo;import?java.util.Calendar;/**?*?@author?taoGG?*?@description?jdk?5.0?之前?抽象類枚舉方案Demo?*?@create?2020-09-13?14:20?*/public?class?EnumDemo01?{????public?static?void?main(String[]?args)?{????????Calendar?calendar?=?Calendar.getInstance();????????System.out.println(calendar.get(Calendar.YEAR));????}}我們運(yùn)行進(jìn)行輸出:
2020Process?finished?with?exit?code?0結(jié)果與之前一致,這時(shí)我們就清楚,在開發(fā)過程中作為開發(fā)者我們肯定愿意使用 Calendar.YEAR 這種寫法,一來(lái)方便記憶,二來(lái)可讀性高。那么官方的做法時(shí)怎樣的呢?我們點(diǎn)進(jìn)去源碼看一下
2. 定義一個(gè)接口,在接口中定義常量維護(hù)枚舉值
我們新建一個(gè)interface CustomerInf.java
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?接口常量維護(hù)枚舉值?*?@create?2020-09-13?15:47?*/public?interface?CustomerInf?{???int?RED?=?1;???int?GREEN?=?2;???int?BLUE?=?3;}在 EnumTest 進(jìn)行測(cè)試
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?Java枚舉測(cè)試類?*?@create?2020-09-13?14:54?*?*/public?class?EnumTest?{????public?static?void?main(String[]?args)?{????????System.out.println(CustomerInf.RED);????}}測(cè)試結(jié)果:
1Process?finished?with?exit?code?0這種做法我們達(dá)到了和在抽象類中維護(hù)常量相同的目的。上面這兩種做法都非常的簡(jiǎn)單易用,但也有弊端。比如我們只知道一個(gè)狀態(tài)值,當(dāng)我們要獲取狀態(tài)的屬性或者相關(guān)的內(nèi)容時(shí),我們?cè)撛趺醋瞿?#xff1f;
下面我們使用第三種方式,自定義枚舉類,這種基本上達(dá)到和 Enum 關(guān)鍵字相同的作用,但有一點(diǎn)不足就是會(huì)較為復(fù)雜
3.自定義枚舉類,通過為類私有化構(gòu)造器和固定實(shí)例對(duì)象進(jìn)行枚舉維護(hù)
新建一個(gè)class SeasonEnum.java,代碼如下:
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?15:58?*/public?class?SeasonEnum?{????//1.聲明枚舉對(duì)象的屬性????private?final?String?seasonName;????private?final?int?code;????//2.私有化類的構(gòu)造器????private?SeasonEnum(String?seasonName,int?code){????????this.seasonName?=?seasonName;????????this.code?=?code;????}????//3.提供當(dāng)前枚舉類的多個(gè)對(duì)象?public?static?final????public?static?final?SeasonEnum?SPRING?=?new?SeasonEnum("春天",100);????public?static?final?SeasonEnum?SUMMER?=?new?SeasonEnum("夏天",200);????public?static?final?SeasonEnum?AUTUMN?=?new?SeasonEnum("秋天",300);????public?static?final?SeasonEnum?WINTER?=?new?SeasonEnum("冬天",400);????//4.為類提供獲取屬性的方法????public?String?getSeasonName()?{????????return?seasonName;????}????public?int?getCode()?{????????return?code;????}????//5.重寫toString方法????@Override????public?String?toString()?{????????return?"SeasonEnum{"?+????????????????"seasonName='"?+?seasonName?+?'''?+????????????????",?code="?+?code?+????????????????'}';????}}新建一個(gè)class SeasonEnumTest 進(jìn)行測(cè)試,當(dāng)我們通過自定義枚舉類引用實(shí)例對(duì)象時(shí),如下圖可以看到,我們已經(jīng)可以獲取到我們的枚舉對(duì)象了。
獲取到枚舉對(duì)象,我們當(dāng)然也可以獲取到對(duì)應(yīng)的屬性及方法,這種可用性就提高了很多,我們?cè)陂_發(fā)程序進(jìn)行判斷,可以根據(jù)各種枚舉值的指定屬性來(lái)進(jìn)行,提高了代碼的可維護(hù)性。
SeasonEnumTest 測(cè)試代碼
根據(jù)我們上面的自定義枚舉類方式,我們基本已經(jīng)實(shí)現(xiàn)了枚舉的功能了,但是就像上面說到的,如果開發(fā)中枚舉類型較多,開發(fā)多個(gè)這樣的自定義枚舉類會(huì)非常的耗時(shí),所以 jdk 5.0 之后,推出了 Enum 關(guān)鍵字定義枚舉類
(三)Enum 關(guān)鍵字定義枚舉類(jdk 5.0之后)
enum 全稱為 enumeration,是jdk 5.0 中引入的新特性,在Java 中被 enum 關(guān)鍵字修飾的類型就是枚舉類型
我們通過代碼來(lái)示例來(lái)講解和理解 enum 的用法,還是用我們剛剛自定以枚舉類的例子,看看使用enum如何來(lái)寫
新建一個(gè)Java class ,Kind 類型選擇 enum 如圖:
枚舉類創(chuàng)建注意:
- 枚舉實(shí)例必須在 enum關(guān)鍵字聲明的類中顯式的指定(首行開始的以第一個(gè)分號(hào)結(jié)束)
- 枚舉不允許使用new,clone,反射,序列化手動(dòng)創(chuàng)建枚舉實(shí)例
使用 SeasonTest 測(cè)試類進(jìn)行測(cè)試:
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?16:27?*/public?class?SeasonTest?{????public?static?void?main(String[]?args)?{????????Season?spring?=?Season.SPRING;????????System.out.println(spring);????}}輸出結(jié)果:
SPRINGProcess?finished?with?exit?code?0注意,在enmu 枚舉類中如果沒有重寫 toString方法,會(huì)默認(rèn)使用Enum類本身提供的 toString 方法,返回枚舉類名稱,因?yàn)槎x的枚舉類默認(rèn)隱式繼承于java.lang.Enum
1.枚舉類主要方法介紹
- values() :該方法可以返回當(dāng)前枚舉類型的對(duì)象數(shù)組,可以很方便的遍歷所有枚舉值。一般我們可以根據(jù)枚舉類的相關(guān)屬性通過此方法遍歷獲取對(duì)應(yīng)的枚舉對(duì)象及枚舉值
- valueOf(String str) : 根據(jù)枚舉類名稱獲取枚舉類對(duì)象
- toString(): 默認(rèn)使用 java.lang.Enum的 toString方法,返回當(dāng)前對(duì)象常量的名稱,枚舉類推薦重寫返回自定義友好描述
- name(): 返回當(dāng)前枚舉對(duì)象名稱,和toString作用上類似,當(dāng)時(shí)toString支持重寫,name方法是不能重寫的,在本質(zhì)上 toString 也是調(diào)用的 name方法,枚舉定義 name 方法就是為了返回枚舉對(duì)象名稱,而 toString 應(yīng)該根據(jù)需要進(jìn)行重寫
- ordinal(): 返回當(dāng)前枚舉對(duì)象的序號(hào), 實(shí)現(xiàn)了 Comparable 接口,表明它是支持排序的 可以通過 Collections.sort 進(jìn)行自動(dòng)排序比較此枚舉與指定對(duì)象的順序
- compareTo(): 基于ordinal進(jìn)行序號(hào)大小比較
方式演示代碼,小伙伴們可以自行運(yùn)行輸出一下,看看各個(gè)方法的作用,熟悉一下相關(guān)的方法api
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?16:27?*/public?class?SeasonTest?{????public?static?void?main(String[]?args)?{????????System.out.println("========values()方法=======");????????for?(Season?season?:?Season.values())?{????????????System.out.println(season);????????}????????System.out.println("===========================");?????????System.out.println("========valueOf方法========");????????Season?spring?=?Season.valueOf("SPRING");????????System.out.println(spring);????????System.out.println("===========================");????????System.out.println("========toString方法========");????????System.out.println(spring.toString());????????System.out.println("===========================");????????System.out.println("========name方法========");????????System.out.println(spring.name());????????System.out.println("===========================");????????System.out.println("========ordinal方法========");????????System.out.println(spring.ordinal());????????System.out.println("===========================");????????System.out.println("========compareTo方法========");????????System.out.println(spring.compareTo(Season.WINTER));????????System.out.println("===========================");????}}2.枚舉類對(duì)接口的實(shí)現(xiàn)方式
準(zhǔn)備工作
新建一個(gè)EnumInf 接口,定義一個(gè)抽象方法
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?17:25?*/public?interface?EnumInf?{????void?show();}1.實(shí)現(xiàn)接口,在enum中統(tǒng)一實(shí)現(xiàn)抽象方法
新建一個(gè)EnumInf 接口,定義抽象方法 show()
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?17:25?*/public?interface?EnumInf?{????void?show();}新建一個(gè)OrderStatus 枚舉類 實(shí)現(xiàn) EnumInf 接口
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?17:27?*/public?enum?OrderStatus?implements?EnumInf{????SUCCESS(200,"交易成功"),????Fail(500,"交易失敗");????private?final?int?code;????private?final?String?desc;????OrderStatus(int?code,?String?desc){????????this.code?=?code;????????this.desc?=?desc;????}????public?int?getCode()?{????????return?code;????}????public?String?getDesc()?{????????return?desc;????}????/**?????*?第一種方式,枚舉統(tǒng)一重寫接口抽象方法?????*/????@Override????public?void?show()?{????????System.out.println("訂單枚舉對(duì)象");????}}進(jìn)行測(cè)試
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?17:32?*/public?class?OrderStatusTest?{????public?static?void?main(String[]?args)?{????????OrderStatus?success?=?OrderStatus.SUCCESS;????????success.show();????}}輸出結(jié)果
訂單枚舉對(duì)象Process?finished?with?exit?code?0跟我們常用類實(shí)現(xiàn)沒有什么區(qū)別,枚舉也是可以統(tǒng)一實(shí)現(xiàn)的,那如果想針對(duì)不同的枚舉對(duì)象進(jìn)行不同狀態(tài)的實(shí)現(xiàn)怎么辦呢?比如我們的OA系統(tǒng)、或者電商系統(tǒng)中,根據(jù)不同狀態(tài) 我們需要回寫對(duì)應(yīng)的數(shù)據(jù),下面我們就來(lái)看看如何實(shí)現(xiàn)。
2.枚舉對(duì)象分別實(shí)現(xiàn)接口中的抽象方法
案例跟接口統(tǒng)一實(shí)現(xiàn)一致,我們這邊修改一下OrderStatus 枚舉類,代碼如下
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?17:27?*/public?enum?OrderStatus?implements?EnumInf{????SUCCESS(200,"交易成功")?{????????@Override????????public?void?show()?{????????????System.out.println("回寫交易成功狀態(tài)");????????}????},????Fail(500,"交易失敗")?{????????@Override????????public?void?show()?{????????????System.out.println("回寫交易失敗狀態(tài)");????????}????};????private?final?int?code;????private?final?String?desc;????OrderStatus(int?code,?String?desc){????????this.code?=?code;????????this.desc?=?desc;????}????public?int?getCode()?{????????return?code;????}????public?String?getDesc()?{????????return?desc;????}}我們?cè)傩薷南聹y(cè)試類代碼:
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?17:32?*/public?class?OrderStatusTest?{????public?static?void?main(String[]?args)?{????????OrderStatus?success?=?OrderStatus.SUCCESS;????????success.show();????????OrderStatus?fail?=?OrderStatus.Fail;????????fail.show();????}}輸出結(jié)果
回寫交易成功狀態(tài)回寫交易失敗狀態(tài)Process?finished?with?exit?code?0通過這種方式就可以輕而易舉地定義每個(gè)枚舉實(shí)例不同的行為方式,也達(dá)到了我們預(yù)期的效果,其實(shí)在開發(fā)過程中根據(jù)枚舉的設(shè)計(jì)和設(shè)計(jì)模式的鋪墊可以極大的簡(jiǎn)化我們的業(yè)務(wù)代碼。
3.Enum枚舉類的工具類及應(yīng)用場(chǎng)景
1.EnumSet 和 EnumMap
Java 中提供了兩個(gè)方便操作enum的工具類——EnumSet 和 EnumMap。
EnumSet 是枚舉類型的高性能 Set 實(shí)現(xiàn)。它要求放入它的枚舉常量必須屬于同一枚舉類型。
//?EnumSet的使用System.out.println("EnumSet展示");EnumSet?errSet?=?EnumSet.allOf(OrderStatus.class);for?(OrderStatus?e?:?errSet)?{????System.out.println(e.name()?+?"?:?"?+?e.ordinal());}EnumMap 是專門為枚舉類型量身定做的 Map 實(shí)現(xiàn)。雖然使用其它的 Map 實(shí)現(xiàn)(如HashMap)也能完成枚舉類型實(shí)例到值得映射,但是使用 EnumMap 會(huì)更加高效:它只能接收同一枚舉類型的實(shí)例作為鍵值,并且由于枚舉類型實(shí)例的數(shù)量相對(duì)固定并且有限,所以 EnumMap 使用數(shù)組來(lái)存放與枚舉類型對(duì)應(yīng)的值。(計(jì)算機(jī)處理連續(xù)的資源使用局部?jī)?nèi)存效率更高)這使得 EnumMap 的效率非常高。
//?EnumMap的使用System.out.println("EnumMap展示");EnumMap?errMap?=?new?EnumMap(StateMachine.Signal.class);errMap.put(StateMachine.Signal.RED,?"紅燈");errMap.put(StateMachine.Signal.YELLOW,?"黃燈");errMap.put(StateMachine.Signal.GREEN,?"綠燈");for?(Iterator>?iter?=errMap.entrySet().iterator();?iter.hasNext();)?{????Map.Entry?entry?=?iter.next();????System.out.println(entry.getKey().name()?+?"?:?"?+?entry.getValue());}2.枚舉類與 Switch 的配合使用
關(guān)于枚舉與switch是個(gè)比較簡(jiǎn)單的話題,使用switch進(jìn)行條件判斷時(shí),條件參數(shù)一般只能是整型,字符型。而枚舉型確實(shí)也被switch所支持,在java 1.7后switch也對(duì)字符串進(jìn)行了支持。
實(shí)踐
新建一個(gè) BizEnum 的java class,代碼如下
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?企業(yè)類型枚舉?*?@create?2020-09-13?21:24?*/public?enum?BizEnum?{????COUNTRIES(101,"國(guó)有企業(yè)"),????PRIVETE(102,"私營(yíng)企業(yè)"),????SOHO(103,"個(gè)體單位");????private?final?int?code;????private?final?String?desc;????BizEnum(int?code,?String?desc){????????this.code?=?code;????????this.desc?=?desc;????}????public?int?getCode()?{????????return?code;????}????public?String?getDesc()?{????????return?desc;????}????//根據(jù)編碼獲取當(dāng)前枚舉對(duì)象的方法????public?static?BizEnum?getBizTypeByCode(int?code){????????for?(BizEnum?bizEnum?:?BizEnum.values())?{????????????if(code?==?bizEnum.getCode()){????????????????return?bizEnum;????????????}????????}????????return?null;????}}結(jié)合Switch進(jìn)行測(cè)試
package?org.taoguoguo;/**?*?@author?taoGG?*?@description?*?@create?2020-09-13?21:31?*/public?class?BizTest?{????public?static?void?main(String[]?args)?{????????BizEnum?bizType?=?BizEnum.getBizTypeByCode(101);????????switch?(bizType){????????????case?COUNTRIES:????????????????System.out.println("國(guó)有企業(yè)");????????????????break;????????????case?PRIVETE:????????????????System.out.println("私營(yíng)企業(yè)");????????????????break;????????????case?SOHO:????????????????System.out.println("個(gè)體單位");????????????????break;????????????default:????????????????System.out.println("創(chuàng)業(yè)中");????????}????}}輸出結(jié)果:
國(guó)有企業(yè)Process?finished?with?exit?code?0總結(jié)
總結(jié)
以上是生活随笔為你收集整理的枚举类型enum用法_Java枚举深度解读,看这篇就够了的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单例模式双重校验锁_被面试官虐过之后,他
- 下一篇: python编程免费教程电子书_pyth