Java枚举的作用和用法

Wesley13
• 阅读 425

从没有枚举的时代说起

在枚举出现之前,如果想要表示一组特定的离散值,往往使用一些常量。例如:

[Java]  纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public class Entity {

public static final int VIDEO = 1 ; //视频

public static final int AUDIO = 2 ; //音频

public static final int TEXT = 3 ; //文字

public static final int IMAGE = 4 ; //图片

private int id;

private int type;

public int getId() {

return id;

}

public void setId( int id) {

this .id = id;

}

public int getType() {

return type;

}

public void setType( int type) {

this .type = type;

}

}

当然,常量也不仅仅局限于int型,诸如char和String等也是不在少数。然而,无论使用什么样的类型,这样做都有很多的坏处。这些常量通常都是连续、有无穷多个值的量,而类似这种表示类别的量则是离散的,并且通常情况下只有有限个值。用连续的量去表示离散量,会产生很多问题。例如,针对上述的Entity类,如果要对Entity对象的type属性进行赋值,一般会采用如下方法:

[Java]  纯文本查看 复制代码

?

1

2

3

Entity e = new Entity();

e.setId( 10 );

e.setType( 2 );

这样做的缺点有:

(1)代码可读性差、易用性低。由于setType()方法的参数是int型的,在阅读代码的时候往往会让读者感到一头雾水,根本不明白这个2到底是什么意思,代表的是什么类型。当然,要保证可读性,还有这样一个办法:

e.setType(Entity.AUDIO);

而这样的话,问题又来了。这样做,客户端必须对这些常量去建立理解,才能了解如何去使用这个东西。说白了,在调用的时候,如果用户不到Entity类中去看看,还真不知道这个参数应该怎么传、怎么调。像是setType(2)这种用法也是在所难免,因为它完全合法,不是每个人都能够建立起用常量名代替数值,从而增加程序可读性、降低耦合性的意识。

(2)类型不安全。在用户去调用的时候,必须保证类型完全一致,同时取值范围也要正确。像是setType(-1)这样的调用是合法的,但它并不合理,今后会为程序带来种种问题。也许你会说,加一个有效性验证嘛,但是,这样做的话,又会引出下面的第(3)个问题。

(3)耦合性高,扩展性差。假如,因为某些原因,需要修改Entity类中常量的值,那么,所有用到这些常量的代码也就都需要修改——当然,要仔细地修改,万一漏了一个,那可不是开玩笑的。同时,这样做也不利于扩展。例如,假如针对类别做了一个有效性验证,如果类别增加了或者有所变动,则有效性验证也需要做对应的修改,不利于后期维护。

认识枚举

枚举(enum),是指一个经过排序的、被打包成一个单一实体的项列表。一个枚举的实例可以使用枚举项列表中任意单一项的值。枚举在各个语言当中都有着广泛的应用,通常用来表示诸如颜色、方式、类别、状态等等数目有限、形式离散、表达又极为明确的量。Java从JDK5开始,引入了对枚举的支持。

使用枚举解决我们前面遇到的问题

枚举就是为了这样的问题而诞生的。它们给出了将一个任意项同另一个项相比较的能力,并且可以在一个已定义项列表中进行迭代。枚举(在Jave中简称为enum)是一个特定类型的类。所有枚举都是Java中的新类java.lang.Enum的隐式子类。此类不能手工进行子类定义。一个简单的枚举可以是这样:

[Java]  纯文本查看 复制代码

?

1

2

3

public enum TypeEnum {

VIDEO, AUDIO, TEXT, IMAGE

}

上面的Entity类就可以改成这样:

[Java]  纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

public class Entity {

private int id;

private TypeEnum type;

public int getId() {

return id;

}

public void setId( int id) {

this .id = id;

}

public TypeEnum getType() {

return type;

}

public void setType(TypeEnum type) {

this .type = type;

}

}

在为Entity对象赋值的时候,就可以这样:

[Java]  纯文本查看 复制代码

?

1

2

3

Entity e = new Entity();

e.setId( 10 );

e.setType(TypeEnum.AUDIO);

怎么看,都是好了很多。在调用setType()时,可选值只有四个,否则会出现编译错误,因此可以看出,枚举是类型安全的,不会出现取值范围错误的问题。同时,客户端不需要建立对枚举中常量值的了解,使用起来很方便,并且可以容易地对枚举进行修改,而无需修改客户端。如果常量从枚举中被删除了,那么客户端将会失败并且将会收到一个错误消息。枚举中的常量名称可以被打印,因此除了仅仅得到列表中项的序号外还可以获取更多信息。这也意味着常量可用作集合的名称,例如HashMap。

因为在Java中一个枚举就是一个类,它也可以有属性和方法,并且实现接口。只是所有的枚举都继承自java.lang.Enum类,因此enum不可以再继承其他的类。

下面给出在枚举中声明属性和方法的示例:

[Java]  纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

public enum TypeEnum {

VIDEO( 1 ), AUDIO( 2 ), TEXT( 3 ), IMAGE( 4 );

int value;

TypeEnum( int value) {

this .value = value;

}

public int getValue() {

return value;

}

}

在这个枚举中,每个枚举的值都有一个对应的int型字段,而且不同的枚举值也会有不同的int数值。同时,它和普通的类一样,可以声明构造器和各种各样的方法。如:

[Java]  纯文本查看 复制代码

?

1

2

TypeEnum type = TypeEnum.TEXT; //type的value属性值为3。

System.out.println(type.getValue()); //屏幕输出3。

如果要为每个枚举值指定属性,则在枚举中必须声明一个参数为属性对应类型的构造方法(不能是public)。否则编译器将给出The constructor TypeEnum(int, String) is undefined的错误。在此例中,属性为int型,因此构造方法应当为int型。除此之外,还可以为枚举指定多个属性,如:

[Java]  纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

public enum TypeEnum {

VIDEO( 1 , "视频" ), AUDIO( 2 , "音频" ), TEXT( 3 , "文本" ), IMAGE( 4 , "图像" );

int value;

String name;

TypeEnum( int value, String name) {

this .value = value;

this .name = name;

}

public int getValue() {

return value;

}

public String getName() {

return name;

}

}

enum还内置了许多方法,常用的如下:

[Java]  纯文本查看 复制代码

?

1

2

3

4

5

6

7

int compareTo(E o) //比较此枚举与指定对象的顺序。

Class<E> getDeclaringClass() //返回与此枚举常量的枚举类型相对应的 Class 对象。

String name() // 返回此枚举常量的名称,在其枚举声明中对其进行声明。

int ordinal() //返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。

String toString() //返回枚举常量的名称,它包含在声明中。

static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) //返回带指定名称的指定枚举类型的枚举常量。

static T[] values() //返回该枚举的所有值。

现在,假设要为该枚举实现一个根据整数值生成枚举值的方法,可以这样做:

[Java]  纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

public enum TypeEnum {

VIDEO( 1 , "视频" ), AUDIO( 2 , "音频" ), TEXT( 3 , "文本" ), IMAGE( 4 , "图像" );

int value;

String name;

TypeEnum( int value, String name) {

this .value = value;

this .name = name;

}

public int getValue() {

return value;

}

public String getName() {

return name;

}

public static TypeEnum getByValue( int value) {

for (TypeEnum typeEnum : TypeEnum.values()) {

if (typeEnum.value == value) {

return typeEnum;

}

}

throw new IllegalArgumentException( "No element matches " + value);

}

}

getByValue(int)即为整数值转枚举值的方法。调用values()方法获取到该枚举下的所有值,然后遍历该枚举下面的每个值和给定的整数是否匹配,若匹配直接返回,若无匹配值则抛出IllegalArgumentException异常,表示参数不合法,兼有有效性验证的作用。

综上,我们可以看到,在JDK5中新引入的枚举完美地解决了之前通过常量来表示离散量所带来的问题,大大加强了程序的可读性、易用性和可维护性,并且在此基础之上又进行了扩展,使之可以像类一样去使用,更是为Java对离散量的表示上升了一个台阶。因此,如果在Java中需要表示诸如颜色、方式、类别、状态等等数目有限、形式离散、表达又极为明确的量,应当尽量舍弃常量表示的做法,而将枚举作为首要的选择。

更多技术资讯可关注:itheimaGZ获取

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
java枚举用法
java枚举:1、(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fqq_27093465%2Farticle%2Fdetails%2F52180865)Java枚举(enum)详解7种常见的用法(https://www.oschina.net/
Wesley13 Wesley13
2年前
P2P技术揭秘.P2P网络技术原理与典型系统开发
Modular.Java(2009.06)\.Craig.Walls.文字版.pdf:http://www.t00y.com/file/59501950(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.t00y.com%2Ffile%2F59501950)\More.E
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
2年前
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法参考文章:(1)Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.codeprj.com%2Fblo
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
2个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这