java 枚举详解

1. 概述

枚举(enum)全写为的全称为:enumeration。是jdk1.5才新引进的概念,在Java中enum的有与C、C++相似的基本用法,也有很多扩展的用法。

尽管枚举类型看着像一种新的数据类型,但实际上它是一种受限制的类(继承自java.lang.Enum)。

publicenumColorEnum{//相当于创建了5个实例,调用了5次 Enum(String name, int ordinal)RED,WHITE,BLUE,BLACK,GREEN}

1

2

3

4

经过编译器编译后产生的是一个class文件,该class文件经过反编译软件编译后可以看到实际上生成了一个类:

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 基础用法

在未引入enum之前,我们定义常量的时候总是使用这样的方式:public final static 类型....,在引入了枚举类型之后,我们可以将一组相似属性统一组织、管理管理,并包含一些自己的方法:

name():返回枚举常量的名称。

ordinal():返回枚举常量的时序,0、1、2……。

getDeclaringClass():返回实例所属的enum类型。

equals(Object other):判断两个enum实例是否相等,也可用用==号来进行判断。

注意不能用直接用数字常量与枚举类型直接比较。

因为父类Enum实现了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

输出结果:

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时需要注意:

定义的枚举类型不可再继承其他的类型的类,因为它已经继承了java.lang.Enum。

2.2 添加成员、方法

前面介绍过,枚举也是一种类,是一种受限制的类,不能在继承其他任何类的类。因此它也具有类应该有的特性。

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虽然不能直接为实例赋值,但是它有更优秀的解决方案:为 enum 添加方法来间接实现显示赋值。枚举类可以有自己的成员、构造方法、普通方法、抽象方法、静态方法。

唯一用起来比较别扭的一点是,enum相当于把类的实例化(枚举常量)放到了类声明的内部,这些枚举常量也可以重写枚举类型中的方法。

publicenumWeekEnum{//定义枚举常量Mon(true),Tue(true),Wen(true),Thu(true),//定义枚举常量的时候可以重写枚举类型中方法Fri(true){@OverridepublicStringhelloEnum() {return"sad to work";        }    },    Sat(false),Sun(false);//枚举类型中可以有成员变量privatebooleanmIsWork;//枚举类型中可以有构造函数privateWeekEnum(booleanisWork){this.mIsWork = isWork;    }//枚举类型中可以有成员方法publicbooleanisWork(){returnmIsWork;    }publicStringhelloEnum(){return"happy to work";    }//枚举类型中可以静态方法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 实现接口

同样作为类,枚举类型也可以实现接口。用法和普通类的用法一致。

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、枚举的典型应用场景

3 .1 常量

如果enum不添加任何方法的话,枚举的默认值为:从0开始的有序数值,每次递增1

如果定义的枚举类型没有任何方法的话,可以在最后一个实例(常量)后加”,” 或”;” 或什么都不加。

注意:如果枚举类中添加了方法,则必须在最后一个实例后添加”;”

以下三种方式定义都可以:

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 组织枚举

可以将类型相近的枚举通过接口或类组织起来,但是一般用接口方式进行组织。

原因是:Java接口在编译时会自动为enum类型加上public static修饰符;Java类在编译时会自动为enum类型加上static修饰符。看出差异了吗?

没错,就是说,在类中组织enum,如果你不给它修饰为public,那么只能在本包中进行访问。

在接口中不加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 策略枚举(没用过)

这种枚举通过枚举嵌套枚举的方式,将枚举实例(常量)分类处理,虽然没有通过switch语句使用简洁,但是更加灵活。

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","时薪100的人在周五工作8小时的收入:"+ PayrollDay.FRIDAY.pay(8.0,100));Log.d("test enum","时薪100的人在周六工作8小时的收入:"+ PayrollDay.SATURDAY.pay(8.0,100));

1

2

3.5 EnumSet和EnumMap

EnumSet是枚举类型的高性能Set实现。它要求放入它的枚举常量必须属于同一枚举类型。它的使用与其他的set没有什么不同,只是在构造的时候有一些特殊而已。

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

1

2

3

//创建一个之类enum类型的空集合EnumSet enumEnumSet = EnumSet.noneOf(ColorEnum.class);showEnumSetValue(enumEnumSet);enumEnumSet.add(ColorEnum.BLACK);enumEnumSet.add(ColorEnum.BLUE);showEnumSetValue(enumEnumSet);//创建一个指定enum类型的所有实例的集合EnumSet enumEnumSet1 = EnumSet.allOf(ColorEnum.class);showEnumSetValue(enumEnumSet1);//创建一个指定enum初始化内容的集合EnumSet enumEnumSet2 = EnumSet.of(ColorEnum.GREEN,ColorEnum.WHITE);showEnumSetValue(enumEnumSet2);//创建指定类型,指定范围的集合,包含边界数据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实现。虽然使用其它的Map实现(如HashMap)也能完成枚举类型实例到值得映射,但是使用EnumMap会更加高效:它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以EnumMap使用数组来存放与枚举类型对应的值。这使得EnumMap的效率非常高。

EnumMap enumStringEnumMap =newEnumMap(ColorEnum.class);enumStringEnumMap.put(ColorEnum.RED,"红色");enumStringEnumMap.put(ColorEnum.BLUE,"蓝色");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 蓝色enummap key: GREEN value 绿色

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,408评论 4 371
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,690评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,036评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,726评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,123评论 3 296
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,037评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,178评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,964评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,703评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,863评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,333评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,658评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,374评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,195评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,988评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,167评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,970评论 2 279

推荐阅读更多精彩内容