枚举类型enum用法_Java枚举深度解读,看这篇就够了
作者 | 涛GuoGuo的跟屁虫丶博Ke
来源 | urlify.cn/aaamQf
66套java从入门到精通实战课程分享
Java枚举
1、枚举类概念的理解与定义
- 一个类的对象是有限个,确定的,我们称此为枚举类。
- 当需要定义和维护一组常量时,强烈建议使用枚举类。
- 如果一个枚举类中只有一个对象,则可以作为单例模式的实现方式。
通俗的说:一个类被设计为包含固定实例数量的特殊类,我们给他的定义是枚举类。注意: 1.枚举类不能被 new 出来,枚举类因为默认的类修饰符为 final 所以也不能被派生(继承),同理枚举类也不能为当作实现。 2.枚举类自身可以实现接口,既可以进行统一实现重写接口抽象方法,也可以按照枚举类型单个实现重写。
2、枚举类的定义
关于枚举类的定义,这块主要想和大家分享两种方式
- jdk 5.0之前,自定义枚举类方式
- jdk 5.0之后,Enum关键字方式定义
3、实践
(一)、准备工作
我们新建一个 Java Project ,并创建一个包,以及一个测试类
(二)、自定义枚举的三种方式(jdk 5.0 之前)
1. 定义一个抽象类,在抽象类中定义常量进行维护,我们接下来以 Java 类库中的 Calendar 类示例来进行说明
新建一个类 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 结果输出:
2020Process finished with exit code 0
如果熟悉 Calendar API 的小伙伴 应该马上能反应过来,这个是获取当前的年份,类似的值还有
3 - 一年中的第几个星期4 - 一年中的第几个月5 - 当前的日期 ......
但是这么多值,我们怎么能记得住呢?万一我输入错误,随便取了一个范围怎么办?
没错,这是 jdk 5.0之前的痛点,为了解决实例数量固定,便于维护这些问题,在jdk 5.0之后更新Enum枚举类解决了这个问题。那在jdk 5.0之前官方是怎么做的呢?难道需要我们一个个去记住 Calendar 的数字?
实际上官方本身,采用的就是我们现在说的第一种方式,在抽象类中定义常量进行维护
现在我们将代码做些修改:
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)); }}
我们运行进行输出:
2020Process finished with exit code 0
结果与之前一致,这时我们就清楚,在开发过程中作为开发者我们肯定愿意使用 Calendar.YEAR 这种写法,一来方便记忆,二来可读性高。那么官方的做法时怎样的呢?我们点进去源码看一下
- 首先 Calendar 本身是一个抽象类,实现了序列化、克隆、以及比较排序接口,这边和我们枚举没有太大关系,我们继续往下看
- 在抽象类中,定义了很多个静态常量进行维护,而当我们需要使用时,直接调用,这样就比我们写一个个的具体值要方便和易用了。
2. 定义一个接口,在接口中定义常量维护枚举值
我们新建一个interface CustomerInf.java
package org.taoguoguo;/** * @author taoGG * @description 接口常量维护枚举值 * @create 2020-09-13 15:47 */public interface CustomerInf { int RED = 1; int GREEN = 2; int BLUE = 3;}
在 EnumTest 进行测试
package org.taoguoguo;/** * @author taoGG * @description Java枚举测试类 * @create 2020-09-13 14:54 * */public class EnumTest { public static void main(String[] args) { System.out.println(CustomerInf.RED); }}
测试结果:
1Process finished with exit code 0
这种做法我们达到了和在抽象类中维护常量相同的目的。上面这两种做法都非常的简单易用,但也有弊端。比如我们只知道一个状态值,当我们要获取状态的属性或者相关的内容时,我们该怎么做呢?
下面我们使用第三种方式,自定义枚举类,这种基本上达到和 Enum 关键字相同的作用,但有一点不足就是会较为复杂
3.自定义枚举类,通过为类私有化构造器和固定实例对象进行枚举维护
新建一个class SeasonEnum.java,代码如下:
package org.taoguoguo;/** * @author taoGG * @description * @create 2020-09-13 15:58 */public class SeasonEnum { //1.声明枚举对象的属性 private final String seasonName; private final int code; //2.私有化类的构造器 private SeasonEnum(String seasonName,int code){ this.seasonName = seasonName; this.code = code; } //3.提供当前枚举类的多个对象 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 + '}'; }}
新建一个class SeasonEnumTest 进行测试,当我们通过自定义枚举类引用实例对象时,如下图可以看到,我们已经可以获取到我们的枚举对象了。
获取到枚举对象,我们当然也可以获取到对应的属性及方法,这种可用性就提高了很多,我们在开发程序进行判断,可以根据各种枚举值的指定属性来进行,提高了代码的可维护性。
SeasonEnumTest 测试代码
package org.taoguoguo;/** * @author taoGG * @description * @create 2020-09-13 16:04 */public class SeasonEnumTest { public static void main(String[] args) { SeasonEnum spring = SeasonEnum.SPRING; System.out.println("自定义枚举类对象:" + spring); System.out.println("自定义枚举类属性:" + spring.getSeasonName()); System.out.println("自定义枚举类属性:" + spring.getCode()); }}
根据我们上面的自定义枚举类方式,我们基本已经实现了枚举的功能了,但是就像上面说到的,如果开发中枚举类型较多,开发多个这样的自定义枚举类会非常的耗时,所以 jdk 5.0 之后,推出了 Enum 关键字定义枚举类
(三)Enum 关键字定义枚举类(jdk 5.0之后)
enum 全称为 enumeration,是jdk 5.0 中引入的新特性,在Java 中被 enum 关键字修饰的类型就是枚举类型
我们通过代码来示例来讲解和理解 enum 的用法,还是用我们刚刚自定以枚举类的例子,看看使用enum如何来写
新建一个Java class ,Kind 类型选择 enum 如图:
枚举类创建注意:
- 枚举实例必须在 enum关键字声明的类中显式的指定(首行开始的以第一个分号结束)
- 枚举不允许使用new,clone,反射,序列化手动创建枚举实例
package org.taoguoguo;/** * @author taoGG * @description * @create 2020-09-13 16:23 */public enum Season { SPRING("春天",100), SUMMER("夏天",200), AUTUMN("秋天",300), WINTER("冬天",400); private final String seasonName; private final int code; Season(String seasonName, int code){ this.seasonName = seasonName; this.code = code; } public String getSeasonName() { return seasonName; } public int getCode() { return code; }}
使用 SeasonTest 测试类进行测试:
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); }}
输出结果:
SPRINGProcess finished with exit code 0
注意,在enmu 枚举类中如果没有重写 toString方法,会默认使用Enum类本身提供的 toString 方法,返回枚举类名称,因为定义的枚举类默认隐式继承于java.lang.Enum
1.枚举类主要方法介绍
- values() :该方法可以返回当前枚举类型的对象数组,可以很方便的遍历所有枚举值。一般我们可以根据枚举类的相关属性通过此方法遍历获取对应的枚举对象及枚举值
- valueOf(String str) : 根据枚举类名称获取枚举类对象
- toString(): 默认使用 java.lang.Enum的 toString方法,返回当前对象常量的名称,枚举类推荐重写返回自定义友好描述
- name(): 返回当前枚举对象名称,和toString作用上类似,当时toString支持重写,name方法是不能重写的,在本质上 toString 也是调用的 name方法,枚举定义 name 方法就是为了返回枚举对象名称,而 toString 应该根据需要进行重写
- ordinal(): 返回当前枚举对象的序号, 实现了 Comparable 接口,表明它是支持排序的 可以通过 Collections.sort 进行自动排序比较此枚举与指定对象的顺序
- compareTo(): 基于ordinal进行序号大小比较
方式演示代码,小伙伴们可以自行运行输出一下,看看各个方法的作用,熟悉一下相关的方法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.枚举类对接口的实现方式
准备工作
新建一个EnumInf 接口,定义一个抽象方法
package org.taoguoguo;/** * @author taoGG * @description * @create 2020-09-13 17:25 */public interface EnumInf { void show();}
1.实现接口,在enum中统一实现抽象方法
新建一个EnumInf 接口,定义抽象方法 show()
package org.taoguoguo;/** * @author taoGG * @description * @create 2020-09-13 17:25 */public interface EnumInf { void show();}
新建一个OrderStatus 枚举类 实现 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; } /** * 第一种方式,枚举统一重写接口抽象方法 */ @Override public void show() { System.out.println("订单枚举对象"); }}
进行测试
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(); }}
输出结果
订单枚举对象Process finished with exit code 0
跟我们常用类实现没有什么区别,枚举也是可以统一实现的,那如果想针对不同的枚举对象进行不同状态的实现怎么办呢?比如我们的OA系统、或者电商系统中,根据不同状态 我们需要回写对应的数据,下面我们就来看看如何实现。
2.枚举对象分别实现接口中的抽象方法
案例跟接口统一实现一致,我们这边修改一下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("回写交易成功状态"); } }, Fail(500,"交易失败") { @Override public void show() { System.out.println("回写交易失败状态"); } }; 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; }}
我们再修改下测试类代码:
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(); }}
输出结果
回写交易成功状态回写交易失败状态Process finished with exit code 0
通过这种方式就可以轻而易举地定义每个枚举实例不同的行为方式,也达到了我们预期的效果,其实在开发过程中根据枚举的设计和设计模式的铺垫可以极大的简化我们的业务代码。
3.Enum枚举类的工具类及应用场景
1.EnumSet 和 EnumMap
Java 中提供了两个方便操作enum的工具类——EnumSet 和 EnumMap。
EnumSet 是枚举类型的高性能 Set 实现。它要求放入它的枚举常量必须属于同一枚举类型。
// EnumSet的使用System.out.println("EnumSet展示");EnumSet errSet = EnumSet.allOf(OrderStatus.class);for (OrderStatus e : errSet) { System.out.println(e.name() + " : " + e.ordinal());}
EnumMap 是专门为枚举类型量身定做的 Map 实现。虽然使用其它的 Map 实现(如HashMap)也能完成枚举类型实例到值得映射,但是使用 EnumMap 会更加高效:它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值。(计算机处理连续的资源使用局部内存效率更高)这使得 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 的配合使用
关于枚举与switch是个比较简单的话题,使用switch进行条件判断时,条件参数一般只能是整型,字符型。而枚举型确实也被switch所支持,在java 1.7后switch也对字符串进行了支持。
实践
新建一个 BizEnum 的java class,代码如下
package org.taoguoguo;/** * @author taoGG * @description 企业类型枚举 * @create 2020-09-13 21:24 */public enum BizEnum { COUNTRIES(101,"国有企业"), PRIVETE(102,"私营企业"), SOHO(103,"个体单位"); 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; } //根据编码获取当前枚举对象的方法 public static BizEnum getBizTypeByCode(int code){ for (BizEnum bizEnum : BizEnum.values()) { if(code == bizEnum.getCode()){ return bizEnum; } } return null; }}
结合Switch进行测试
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("国有企业"); break; case PRIVETE: System.out.println("私营企业"); break; case SOHO: System.out.println("个体单位"); break; default: System.out.println("创业中"); } }}
输出结果:
国有企业Process finished with exit code 0
总结
- jdk 5.0之前我们可以自定义枚举类,jdk 5.0之后使用enum关键字定义枚举类,枚举类默认继承自java.lang.Enum,使用枚举类将常量组织起来,便于统一管理。例如错误码、状态机等场景中,较为合适使用枚举类。
- 枚举类常用方法介绍及枚举类实现抽象类、接口等抽象方法的两种方式。
- 枚举常用的工具类及与switch使用的场景。
枚举类型enum用法_Java枚举深度解读,看这篇就够了相关推荐
- java枚举类型enum用法_java枚举类型enum用法和原理介绍【传智播客】
Enum枚举类型 Enum的全写是Enumeration,这个词的翻译是列举.逐条陈述.细目.在程序语言中,枚举类型是一种特殊的数据类型(常用的数据类型比如字符串.整型),这种数据类型的变量值限定在固 ...
- java枚举类型enum用法_Java枚举类型——Enum的简单用法
枚举类型是Java1.5的新特性,是指由一组固定的常量组成合法的类型.Java中由关键字enum来定义一个枚举类型.我们可以使用枚举来取代用public final static修饰的一批相关数据.如 ...
- python中枚举类型enum用法_Python枚举类型Enum用法详解
实际开发中,我们离不开定义各种类型,当我们需要定义类型时,一般是通过一组整数来定义.比如:定义不同的月份 JAN 1 FEB 2 MAR 3 ... NOV 11 DEC 12 复制代码 大多数人想到 ...
- c语言枚举类型enum用法参数,C语言枚举类型(Enum)
在实际编程中,有些数据的取值往往是有限的,只能是非常少量的整数,并且最好为每个值都取一个名字,以方便在后续代码中使用,比如一个星期只有七天,一年只有十二个月,一个班每周有六门课程等. 以每周七天为例, ...
- java的枚举类型是什么_什么是枚举(java枚举类型enum用法)
最佳回答 枚举 1.枚举 (enumeration) 值类型的一种特殊形式,它从 System.Enum 继承,并为基础基元类型的值提供备用名称.枚举类型有名称.基础类型和一组字段.基础类型. &qu ...
- 枚举类型enum用法赋值
枚举常量是一种枚举类型中的值,及枚举值,枚举类型是由用户自定义的,只用用户在程序中定义它才能被使用.创建一个枚举类型的基本语法: enum 枚举类型名{ 枚举值1,枚举值2,- } 枚举类型名是由用户 ...
- c枚举类型enum例题_c枚举类型enum用法 枚举类型enum用法 怎么去取所有
JUDGE(S W ) 指 W 属于 S 枚举类型还是自定义函数里的2个变量不要太久太久不联系我,我怕我一不小心把你忘了. (1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素 ...
- mysql枚举类型enum用法_mysql中枚举类型之enum详解
enum类型就是我们常说的枚举类型,它的取值范围需要在创建表时通过枚举方式(一个个的列出来)显式指定,对1至255个成员的枚举需要1个字节存储: 对于255至65535个成员,需要2个字节存储.最多允 ...
- Java - 枚举类型enum用法
目录 一.枚举的理解(概念) 二.早期实现方式 三.枚举类型的定义 四. 枚举类的要求和特点 五. 枚举类型常用方法 一.枚举的理解(概念)
最新文章
- 如何理解和评价机器学习中的表达能力、训练难度和泛化性能
- python常用内置模块-Python-常用的内置模块
- 用鸽 计算机教案,科学活动教案:鸽子
- 西裤哥的 Hook Api Lib 0.2 For C
- 使用 JSSE 定制 SSL 连接的属性--转载
- 卡尔曼滤波与组合导航原理_卫星知识科普:一种基于卫星共视的卡尔曼滤波算法!...
- 技术部门Leader是不是一定要技术大牛担任?
- 将VC++6.0的代码迁移到VS2005常见问题总结(Window核心编程第五版以前代码在VS2005无法编译的解决方案)...
- 密钥文件登录服务器,密钥文件登录云服务器
- 关于Java基础你不得不会的34个问题
- USACO-Section2.1 The Castle (深度优先搜索)
- java中list方法addall怎么写_简历中个人优势怎么写?| 四大方法教你打造独一无二“个人标签”...
- 滴滴这车值不值得上?前Google全球技术总监郄小虎说来来来
- 邮箱服务器退回,发出去的邮件为什么被退回?
- 常见Sqlite管理工具
- 《高性能MySQL》读书笔记(1~6章)
- 全新V10抢单系统唯品会/京东/淘宝自动抢单区块系统源码
- 计算机维修高级技能,高级计算机维修工操作技能考核试卷
- WIN10桌面文件夹图标变黑解决方法~
- 大写汉字转阿拉伯数字c语言,使用C#实现阿拉伯数字到大写中文的转换