
【java】可动态扩展的枚举
在Java中,枚举(Enum)是一种特殊的类,用于表示一组有限的、预定义的常量集合。枚举在Java语言中是一种基本数据类型,它是通过关键字**enum**来定义的。如下:我们定义了颜色类型的枚举,包含三种颜色// 定义一个颜色枚举类型 enum Color {RED , // 红色 GREEN , // 绿色 BLUE;// 蓝色 }是不是发现很简单。是的枚举的定义就是这么简单。我们现在是思考一个
可动态扩展的枚举
枚举
什么是枚举?
枚举本质上是一组有限的特殊定义的数据集合。枚举常量通常用于表示一组相关的离散取值,比如颜色、星期几、方向等。
在编程中,枚举是一种更好地表达代码意图的方式,可以增加代码的可读性和可维护性。使用枚举可以将一组相关的常量进行命名,并将其组织在一个统一的类型中,这样可以避免使用硬编码的数字或字符串,减少出错的可能性。
在Java中我们如何定义枚举?
在Java中,枚举(Enum)是一种特殊的类,用于表示一组有限的、预定义的常量集合。枚举在Java语言中是一种基本数据类型,它是通过关键字**enum
**来定义的。
如下:我们定义了颜色类型的枚举,包含三种颜色
// 定义一个颜色枚举类型
enum Color {
RED, // 红色
GREEN,// 绿色
BLUE; // 蓝色
}
是不是发现很简单。是的枚举的定义就是这么简单。
我们现在是思考一个问题,如果我想给这个枚举添加属性该怎么做?
比如我们定义一个日期的枚举,需要输出中文的名词,该怎么做?如下是我们定义的方式。
enum Day {
MONDAY("星期一"),
TUESDAY("星期二"),
WEDNESDAY("星期三"),
THURSDAY("星期四"),
FRIDAY("星期五"),
SATURDAY("星期六"),
SUNDAY("星期日");
private String chineseName;
Day(String chineseName) {
this.chineseName = chineseName;
}
public String getChineseName() {
return chineseName;
}
}
是不是发现,我们需要在枚举类 Day
中定义一个成员变量属性 chineseName
,并且通过构造的方式进行赋值,并且还必须提供 getChineseName
方法,才可以获取到该枚举的属性值。
假如,我们还需要数值型的表示形式,我们就必须补充一个成员变量属性,并且提供相应的取值方法,比如:添加了一个 dayInt 属性
enum Day {
MONDAY("星期一", 1),
TUESDAY("星期二", 2),
WEDNESDAY("星期三", 3),
THURSDAY("星期四", 4),
FRIDAY("星期五", 5),
SATURDAY("星期六", 6),
SUNDAY("星期日", 7);
private String chineseName;
private int dayInt;
Day(String chineseName, int dayInt) {
this.chineseName = chineseName;
this.dayInt = dayInt;
}
public String getChineseName() {
return chineseName;
}
public String getDayInt() {
return dayInt;
}
}
是不是发现,只要我们想补充属性的话,就必须添加对应的成员变量,并且补充对应的取值方法?
是不是发现这种方式不够优雅,如果我们定义很多的枚举,而且枚举都是有好几个相同的成员变量属性,我们还是必须要在每个枚举中一一进行定义?还有对应的方法?
这不是很简单嘛,java 不是可以继承嘛,我只要用一个抽象类,定义好相同的属性,子类枚举进行继承不久OK啦,哈哈哈,我真是小天才。
当你按照这样的思路去操作的时候,你会突然发现,哦呦,桥豆妈的
Java 枚举既然不支持继承????
头皮都开了是不是?
为什么Java 枚举不能进行继承?
Java 的枚举类型是通过关键字**enum
**定义的,不知道大家有没有观察过编译后的枚举类,它们在编译时被转换成一个特殊的类。而且是继承 java/lang/Enum
对象的。
如下图:
// class version 52.0 (52)
// access flags 0x4031
public final enum xxx/xxx/Day extends java/lang/Enum {
...// 省略实际内容
}
看到了吧,final 修饰,而且java中是只能单继承的,这也就解释了为什么java中枚举不能进行继承了。
总结一下
性能:
- 枚举的性能非常高,因为枚举常量在类加载时就被实例化,且只会实例化一次,之后都是直接引用这些实例。
- 枚举类型中的常量是在编译时确定的,不需要动态创建对象,因此不会产生额外的对象创建开销。
优点:
- 类型安全:枚举是类型安全的,编译器会在编译时进行类型检查,确保枚举常量在声明的枚举类型范围内。
- 易读性和可维护性:枚举常量是有意义的命名,使得代码更加清晰易读,并且在后续的代码维护中也更加稳定可靠。
- 单例模式:每个枚举常量只会被实例化一次,保证了每个常量只有一个实例,可以用于实现单例模式。
- 线程安全:枚举类型的实例化是线程安全的,不需要额外的同步措施。
缺点:
枚举常量在编译时就确定了,无法在运行时动态添加新的常量,因此不适合表示动态变化的数据。
由于枚举中存在的局限性,还有小编在实际生产使用中遇到的问题,小编自己写了一个关于可扩展枚举的 java 工具包,欢迎大家体验。下面由小编进行介绍一下:
Extutil 工具包
关于该工具的想法来源,起初是因为在项目开发的过程中,数据库的一些状态字段经常需要用到枚举去定义,通常情况下我们会如下定义:
public enum Status {
USE("E","E","E-在用"),
DELETE("D","D","D-删除");
// 当我们需要扩展属性的时候,必须先定义,而且不能通过继承的方式继承这些属性,如果在定义一个新的类 Status2 的枚举,还需要重新copy定义下面的部分
private String name;
private String code;
private String desc;
... 省略 get set 构造方法
}
如果我们数据库定义和很多的状态,同时这些状态都规定要用枚举去定义,而且如果他们都需要 name,code,desc 三个属性,那对应的将生成很多的冗余代码,很不优雅。
这里我介绍一下关于 Extutil 包下如何使用自定义枚举
定义枚举
方式一:通用方式
这里我们通过继承抽象类 BEnum ,EUtils的bdr()方法构建自定义枚举的效果,例如:
该抽象类枚举定义了通用的三个属性 name,code,desc
其中 code 属性是唯一且必须的属性
// 通过继承 BEnum 构建自定义枚举
public class Status extends BEnum {
public final static Status USE = EUtils.bdr("E", "E", "E-在用", Status.class);
public final static Status DELETE = EUtils.bdr("D", "D", "D-删除", Status.class);
}
方式二:自定义扩展属性
通过 Wrappers.lambdaExpand() 的方式去扩展和自定义属性【无限扩展】
通过枚举通用的方法 apply() 获取枚举字段映射的值
public class Status extends BEnum {
public final static Status USE = EUtils.bdr(Wrappers.lambdaExpand()
.ext("name","E")
.ext("code","E")
.ext("desc","E-在用")
.ext("english","use")
.ext("sort","1")
.ext("remark","E-在用"), Status.class);
public final static Status DELETE = EUtils.bdr(Wrappers.lambdaExpand()
.ext("code","D")
.ext("desc","D-删除"), Status.class);
}
// 获取枚举自定义属性的值 Status.USE.apply("字段")
Status.USE.apply("code"); // 获取字段 code 的值,值为 E
工具类 EUtils 的使用
EUtils 工具类不仅用于枚举的定义,还提供了一些枚举的通用方法
// 获取自定义枚举类 Status 的 map 集合
Map<String, BEnum> benumMap = EUtils.getEnumMap(Status.class)
// 获取自定义枚举类 Status 的 list 集合
List<BEnum> benumList = EUtils.getEnumList(Status.class)
// 根据 code 获取 Status 对象
Status e = EUtils.getEnumList(Status.class, "E")
Maven 库
快速开始使用体验,只需要在工程中引入以下依赖即可
<dependency>
<groupId>cn.com.openboot</groupId>
<artifactId>extutil-enums</artifactId>
<version>1.0.1-beta</version>
</dependency>
源码小编已经发布到 gitee 仓库,欢迎大家关注,三人行,必有我师焉,小编一定还存在不足的地方,希望大家多给小编提提建议,大家一起进步。
gitee 地址:
更多推荐
所有评论(0)