java 枚舉詳解

1. 概述

枚舉(enum)全寫為的全稱為:enumeration。是jdk1.5才新引進(jìn)的概念,在Java中enum的有與C、C++相似的基本用法,也有很多擴(kuò)展的用法。

盡管枚舉類型看著像一種新的數(shù)據(jù)類型,但實(shí)際上它是一種受限制的類(繼承自java.lang.Enum)。

publicenumColorEnum{//相當(dāng)于創(chuàng)建了5個(gè)實(shí)例,調(diào)用了5次 Enum(String name, int ordinal)RED,WHITE,BLUE,BLACK,GREEN}

1

2

3

4

經(jīng)過編譯器編譯后產(chǎn)生的是一個(gè)class文件,該class文件經(jīng)過反編譯軟件編譯后可以看到實(shí)際上生成了一個(gè)類:

publicclasscom.com.yarward.design.ColorEnumextendsjava.lang.Enum{publicstaticfinalcom.com.yarward.design.ColorEnum RED;publicstaticfinalcom.com.yarward.design.ColorEnum WHITE;publicstaticfinalcom.com.yarward.design.ColorEnum BLUE;publicstaticfinalcom.com.yarward.design.ColorEnum BLACK;publicstaticfinalcom.com.yarward.design.ColorEnum GREEN;static{};publicstaticcom.com.yarward.design.ColorEnum[]values();publicstaticcom.com.yarward.design.ColorEnumvalueOf(java.lang.String);? ? ....}

1

2

3

4

5

6

7

8

9

10

11

/** * This is the common base class of all Java language enumeration types. * *

Note that when using an enumeration type as the type of a set * or as the type of the keys in a map, specialized and efficient * {@linkplain java.util.EnumSet set} and {@linkplain * java.util.EnumMap map} implementations are available. * * @since1.5 */publicabstractclassEnum>implementsComparable,Serializable{...}

1

2

3

4

5

6

7

8

9

10

11

12

2. 特性介紹

2.1 基礎(chǔ)用法

在未引入enum之前,我們定義常量的時(shí)候總是使用這樣的方式:public final static 類型....,在引入了枚舉類型之后,我們可以將一組相似屬性統(tǒng)一組織、管理管理,并包含一些自己的方法:

name():返回枚舉常量的名稱。

ordinal():返回枚舉常量的時(shí)序,0、1、2……。

getDeclaringClass():返回實(shí)例所屬的enum類型。

equals(Object other):判斷兩個(gè)enum實(shí)例是否相等,也可用用==號(hào)來進(jìn)行判斷。

注意不能用直接用數(shù)字常量與枚舉類型直接比較。

因?yàn)楦割怑num實(shí)現(xiàn)了Comparable和Serializable的接口,因此也可以使用compareTo()方法。

例:

ColorEnum colorEnumWhite = ColorEnum.WHITE;ColorEnum colorEnumRed = ColorEnum.RED;Log.d("test enum","enum colorEnumRed.toString() is "+ colorEnumRed.toString());Log.d("test enum","enum colorEnumWhite is "+ colorEnumWhite);Log.d("test enum","enum constant name is "+ colorEnumWhite.name());Log.d("test enum","enum constant ordinal is "+ colorEnumWhite.ordinal());Log.d("test enum","enum getDeclaringClass is "+ colorEnumWhite.getDeclaringClass());Log.d("test enum","enum colorEnumWhite = colorEnumRed "+ colorEnumWhite.equals(colorEnumRed));Log.d("test enum","enum colorEnumWhite = 1 "+ colorEnumWhite.equals(1));Log.d("test enum","enum colorEnumWhite compareTo colorEnumRed "+ colorEnumWhite.compareTo(colorEnumRed));

1

2

3

4

5

6

7

8

9

10

11

輸出結(jié)果:

enumcolorEnumRed.toString() is REDenumcolorEnumWhite is WHITEconstant name is WHITEconstant ordinal is1getDeclaringClass is class com.yarward.design.MainActivity$ColorEnumenumcolorEnumWhite = colorEnumRedfalseenumcolorEnumWhite =1falseenumcolorEnumWhite compareTo colorEnumRed1

1

2

3

4

5

6

7

8

在使用enum時(shí)需要注意:

定義的枚舉類型不可再繼承其他的類型的類,因?yàn)樗呀?jīng)繼承了java.lang.Enum。

2.2 添加成員、方法

前面介紹過,枚舉也是一種類,是一種受限制的類,不能在繼承其他任何類的類。因此它也具有類應(yīng)該有的特性。

java中的枚舉與c/c++中的枚舉不同,c/c++可以顯示的為枚舉類型賦值,而java中的枚舉不可以。

/*C/C++可以顯示的給枚舉類型賦值*/typedef enum _Number{

? one = 1,

? two,

? three,

? ten = 10

}Number;

1

2

3

4

5

6

7

Java雖然不能直接為實(shí)例賦值,但是它有更優(yōu)秀的解決方案:為 enum 添加方法來間接實(shí)現(xiàn)顯示賦值。枚舉類可以有自己的成員、構(gòu)造方法、普通方法、抽象方法、靜態(tài)方法。

唯一用起來比較別扭的一點(diǎn)是,enum相當(dāng)于把類的實(shí)例化(枚舉常量)放到了類聲明的內(nèi)部,這些枚舉常量也可以重寫枚舉類型中的方法。

publicenumWeekEnum{//定義枚舉常量Mon(true),Tue(true),Wen(true),Thu(true),//定義枚舉常量的時(shí)候可以重寫枚舉類型中方法Fri(true){@OverridepublicStringhelloEnum() {return"sad to work";? ? ? ? }? ? },? ? Sat(false),Sun(false);//枚舉類型中可以有成員變量privatebooleanmIsWork;//枚舉類型中可以有構(gòu)造函數(shù)privateWeekEnum(booleanisWork){this.mIsWork = isWork;? ? }//枚舉類型中可以有成員方法publicbooleanisWork(){returnmIsWork;? ? }publicStringhelloEnum(){return"happy to work";? ? }//枚舉類型中可以靜態(tài)方法publicstaticStringinfoPrint(){return"Monday to Sunday!";? ? } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

WeekEnum tue = WeekEnum.Tue;WeekEnum fri = WeekEnum.Fri;WeekEnum sat = WeekEnum.Sat;Log.d("test enum","enum static method :"+ WeekEnum.infoPrint());Log.d("test enum","enum tue.helloEnum :"+ tue.helloEnum());Log.d("test enum","enum fri.helloEnum :"+ fri.helloEnum());Log.d("test enum","enum fri is work? "+ fri.isWork());Log.d("test enum","enum sat is work? "+ sat.isWork());

1

2

3

4

5

6

7

8

9

enumstaticmethod :Monday to Sunday!enumtue.helloEnum :happy to workenumfri.helloEnum :sad to workenumfri is work?trueenumsat is work?false

1

2

3

4

5

2.3 實(shí)現(xiàn)接口

同樣作為類,枚舉類型也可以實(shí)現(xiàn)接口。用法和普通類的用法一致。

publicinterfaceIDoSomeThing{publicvoiddoJobs();}

1

2

3

publicenumWeekEnum implements IDoSomeThing{? ? Mon(true),Tue(true),Wen(true),Thu(true),Fri(true){@OverridepublicStringhelloEnum() {return"sad to work";? ? ? ? }? ? },? ? Sat(false){@OverridepublicvoiddoJobs() {? ? ? ? ? ? Log.d("test enum","I am at resting");? ? ? ? }? ? },Sun(false);? ...? ...@OverridepublicvoiddoJobs() {? ? ? ? Log.d("test enum","I am at working");? ? }}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

fri.doJobs();

sat.doJobs();

1

2

I am at working

I am at resting

1

2

3、枚舉的典型應(yīng)用場(chǎng)景

3 .1 常量

如果enum不添加任何方法的話,枚舉的默認(rèn)值為:從0開始的有序數(shù)值,每次遞增1

如果定義的枚舉類型沒有任何方法的話,可以在最后一個(gè)實(shí)例(常量)后加”,” 或”;” 或什么都不加。

注意:如果枚舉類中添加了方法,則必須在最后一個(gè)實(shí)例后添加”;”

以下三種方式定義都可以:

enumColorEnum{ RED, WHITE, BLUE, BLACK, GREEN }enumColorEnum{ RED, WHITE, BLUE, BLACK, GREEN, }enumColorEnum{ RED, WHITE, BLUE, BLACK, GREEN; }

1

2

3

3.2 switch中

enumSignal {? ? ? GREEN, YELLOW, RED? }publicclassTrafficLight{Signal color = Signal.RED;publicvoidchange() {switch(color) {caseRED:? ? ? ? ? ? ? color = Signal.GREEN;break;caseYELLOW:? ? ? ? ? ? ? color = Signal.RED;break;caseGREEN:? ? ? ? ? ? ? color = Signal.YELLOW;break;? ? ? ? ? }? ? ? }? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

3.3 組織枚舉

可以將類型相近的枚舉通過接口或類組織起來,但是一般用接口方式進(jìn)行組織。

原因是:Java接口在編譯時(shí)會(huì)自動(dòng)為enum類型加上public static修飾符;Java類在編譯時(shí)會(huì)自動(dòng)為enum類型加上static修飾符。看出差異了嗎?

沒錯(cuò),就是說,在類中組織enum,如果你不給它修飾為public,那么只能在本包中進(jìn)行訪問。

在接口中不加public static修飾詞,也能在其他包中被引用。

publicinterfaceINumberEnum{publicintgetCode();publicStringgetDescription();}

1

2

3

4

publicinterfacePlant{enumVegetable implements INumberEnum {? ? ? ? POTATO(0,"土豆"),? ? ? ? TOMATO(0,"西紅柿");? ? ? ? Vegetable(intnumber, String description) {this.code = number;this.description = description;? ? ? ? }privateintcode;privateString description;@OverridepublicintgetCode() {return0;? ? ? ? }@OverridepublicStringgetDescription() {returnnull;? ? ? ? }? ? }enumFruit implements INumberEnum {? ? ? ? APPLE(0,"蘋果"),? ? ? ? ORANGE(0,"桔子"),? ? ? ? BANANA(0,"香蕉");? ? ? ? Fruit(intnumber, String description) {this.code = number;this.description = description;? ? ? ? }privateintcode;privateString description;@OverridepublicintgetCode() {return0;? ? ? ? }@OverridepublicStringgetDescription() {returnnull;? ? ? ? }? ? }}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

3.4 策略枚舉(沒用過)

這種枚舉通過枚舉嵌套枚舉的方式,將枚舉實(shí)例(常量)分類處理,雖然沒有通過switch語句使用簡(jiǎn)潔,但是更加靈活。

enumPayrollDay {? ? MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(? ? ? ? ? ? PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), FRIDAY(PayType.WEEKDAY), SATURDAY(? ? ? ? ? ? PayType.WEEKEND), SUNDAY(PayType.WEEKEND);privatefinalPayType payType;? ? PayrollDay(PayType payType) {this.payType = payType;? ? }doublepay(doublehoursWorked,doublepayRate) {returnpayType.pay(hoursWorked, payRate);? ? }// 策略枚舉privateenumPayType {? ? ? ? WEEKDAY {doubleovertimePay(doublehours,doublepayRate) {returnhours <= HOURS_PER_SHIFT ?0: (hours - HOURS_PER_SHIFT)? ? ? ? ? ? ? ? ? ? ? ? * payRate /2;? ? ? ? ? ? }? ? ? ? },? ? ? ? WEEKEND {doubleovertimePay(doublehours,doublepayRate) {returnhours * payRate /2;? ? ? ? ? ? }? ? ? ? };privatestaticfinalintHOURS_PER_SHIFT =8;abstractdoubleovertimePay(doublehrs,doublepayRate);doublepay(doublehoursWorked,doublepayRate) {doublebasePay = hoursWorked * payRate;returnbasePay + overtimePay(hoursWorked, payRate);? ? ? ? }? ? }}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

Log.d("test enum","時(shí)薪100的人在周五工作8小時(shí)的收入:"+ PayrollDay.FRIDAY.pay(8.0,100));Log.d("test enum","時(shí)薪100的人在周六工作8小時(shí)的收入:"+ PayrollDay.SATURDAY.pay(8.0,100));

1

2

3.5 EnumSet和EnumMap

EnumSet是枚舉類型的高性能Set實(shí)現(xiàn)。它要求放入它的枚舉常量必須屬于同一枚舉類型。它的使用與其他的set沒有什么不同,只是在構(gòu)造的時(shí)候有一些特殊而已。

publicvoidshowEnumSetValue(EnumSet enumSet){? ? Log.d("enum test","enum set value is : "+ Arrays.toString(enumSet.toArray()));}

1

2

3

//創(chuàng)建一個(gè)之類enum類型的空集合EnumSet enumEnumSet = EnumSet.noneOf(ColorEnum.class);showEnumSetValue(enumEnumSet);enumEnumSet.add(ColorEnum.BLACK);enumEnumSet.add(ColorEnum.BLUE);showEnumSetValue(enumEnumSet);//創(chuàng)建一個(gè)指定enum類型的所有實(shí)例的集合EnumSet enumEnumSet1 = EnumSet.allOf(ColorEnum.class);showEnumSetValue(enumEnumSet1);//創(chuàng)建一個(gè)指定enum初始化內(nèi)容的集合EnumSet enumEnumSet2 = EnumSet.of(ColorEnum.GREEN,ColorEnum.WHITE);showEnumSetValue(enumEnumSet2);//創(chuàng)建指定類型,指定范圍的集合,包含邊界數(shù)據(jù)EnumSet enumEnumSet3 = EnumSet.range(ColorEnum.BLUE,ColorEnum.GREEN);showEnumSetValue(enumEnumSet3);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

enumset value is : []enumset value is : [BLUE, BLACK]enumset value is : [RED, WHITE, BLUE, BLACK, GREEN]enumset value is : [WHITE, GREEN]enumset value is : [BLUE, BLACK, GREEN]

1

2

3

4

5

EnumMap是專門為枚舉類型量身定做的Map實(shí)現(xiàn)。雖然使用其它的Map實(shí)現(xiàn)(如HashMap)也能完成枚舉類型實(shí)例到值得映射,但是使用EnumMap會(huì)更加高效:它只能接收同一枚舉類型的實(shí)例作為鍵值,并且由于枚舉類型實(shí)例的數(shù)量相對(duì)固定并且有限,所以EnumMap使用數(shù)組來存放與枚舉類型對(duì)應(yīng)的值。這使得EnumMap的效率非常高。

EnumMap enumStringEnumMap =newEnumMap(ColorEnum.class);enumStringEnumMap.put(ColorEnum.RED,"紅色");enumStringEnumMap.put(ColorEnum.BLUE,"藍(lán)色");enumStringEnumMap.put(ColorEnum.GREEN,"綠色");for(Map.Entry enumStringEntry : enumStringEnumMap.entrySet()){? ? Log.d("enum test","enum map key: "+enumStringEntry.getKey().name()+" value "+ enumStringEntry.getValue());}

1

2

3

4

5

6

7

8

enummap key: RED value 紅色enummap key: BLUE value 藍(lán)色enummap key: GREEN value 綠色

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容