需求
自己模拟两个枚举,假设业务中需要用到
Example1StatusEnum.java
package com.zdh.zdhenum;
/**
* @author dh
* @date 2024/07/24
* @desc (详细信息)
*/
public enum Example1StatusEnum {
NEW("new", "新建状态"),
FAIL("fail", "失败状态"),
SUCCESS("success", "成功状态"),
CLOSED("closed", "关闭状态");
private String code;
private String description;
Example1StatusEnum(String code, String description) {
this.code = code;
this.description = description;
}
}
Example2StatusEnum .java
package com.zdh.zdhenum;
import com.fasterxml.jackson.databind.ser.Serializers;
/**
* @author dh
* @date 2024/07/24
* @desc (详细信息)
*/
public enum Example2StatusEnum implements BaseEnum {
NEW("new", "新建状态"),
FAIL("fail", "失败状态"),
SUCCESS("success", "成功状态"),
PROCESSING("processing", "处理中状态"),
WAITING("waiting", "等待状态"),
CLOSED("closed", "关闭状态"),
ABANDONED("abandoned", "弃状态");
private String code;
private String description;
Example2StatusEnum(String code, String description) {
this.code = code;
this.description = description;
}
}
实际场景中,可能远远大于2个,每个枚举类内item有唯一的code
,实际业务开发中需要根据唯一的code
获取对应的枚举类型。
原始解决方案
哪个枚举类需要根据code获取对应的枚举,就在该枚举类中添加获取方法
例如Example1StatusEnum
需要根据code获取对应的枚举,在Example1StatusEnum
添加如下方法:
public static Example1StatusEnum toEnum(String code){
for (Example1StatusEnum item : Example1StatusEnum.values()) {
if (Objects.equals(item.getCode(),code)) {
return item;
}
}
return null;
}
同理,其他需要用到此方法,都需要复制上面的方法,并更改为对应类型,大量重复性工作。
优化方案
1. 首先创建base接口。
package com.zdh.zdhenum;
/**
* @author dh
* @date 2024/07/23
* @desc (详细信息)
*/
public interface BaseEnum {
/**
* 获取code
* @return
*/
String getCode();
}
后面工具类根据此接口方法可以 通用的获取code
2. 创建枚举工具类
package com.zdh.zdhenum;
import java.util.Objects;
/**
* @author dh
* @date 2024/07/24
* @desc (详细信息)
*/
public class MyEnumUtil {
public static <E extends Enum<E> & BaseEnum> E toEnumByCode(String code, Class<E> enumClass) {
for (E enumConstant : enumClass.getEnumConstants()) {
if (Objects.equals(enumConstant.getCode(),code)) {
return enumConstant;
}
}
return null;
}
}
<E extends Enum<E> & BaseEnum>
这里泛型,extends 表现必须继承自后面的xxx,BaseEnum
规定必须实现上面定义的BaseEnum接口,Enum<E>
为枚举类的公共父类,规定必须是枚举类可以用此方法。
3. 需要使用工具类的枚举,实现BaseEnum接口即可
例如,Example1StatusEnum
和Example2StatusEnum
都需要使用。
分别修改如下:
package com.zdh.zdhenum;
import java.util.Objects;
/**
* @author dh
* @date 2024/07/24
* @desc (详细信息)
*/
public enum Example1StatusEnum implements BaseEnum{
NEW("new", "新建状态"),
FAIL("fail", "失败状态"),
SUCCESS("success", "成功状态"),
CLOSED("closed", "关闭状态");
private String code;
private String description;
Example1StatusEnum(String code, String description) {
this.code = code;
this.description = description;
}
/**
* 获取code
*
* @return
*/
@Override
public String getCode() {
return this.code;
}
}
package com.zdh.zdhenum;
import com.fasterxml.jackson.databind.ser.Serializers;
/**
* @author dh
* @date 2024/07/24
* @desc (详细信息)
*/
public enum Example2StatusEnum implements BaseEnum {
NEW("new", "新建状态"),
FAIL("fail", "失败状态"),
SUCCESS("success", "成功状态"),
PROCESSING("processing", "处理中状态"),
WAITING("waiting", "等待状态"),
CLOSED("closed", "关闭状态"),
ABANDONED("abandoned", "弃状态");
private String code;
private String description;
Example2StatusEnum(String code, String description) {
this.code = code;
this.description = description;
}
/**
* 获取code
*
* @return
*/
@Override
public String getCode() {
return this.code;
}
}
4. 测试使用
public static void main(String[] args) {
Example1StatusEnum quotaStatusEnum11 = MyEnumUtil.toEnumByCode("new", Example1StatusEnum.class);
System.out.println("quotaStatusEnum11 = " + quotaStatusEnum11);
Example1StatusEnum quotaStatusEnum12 = MyEnumUtil.toEnumByCode("fda", Example1StatusEnum.class);
System.out.println("quotaStatusEnum12 = " + quotaStatusEnum12);
Example2StatusEnum quotaStatusEnum21 = MyEnumUtil.toEnumByCode("new", Example2StatusEnum.class);
System.out.println("quotaStatusEnum11 = " + quotaStatusEnum21);
Example2StatusEnum quotaStatusEnum22 = MyEnumUtil.toEnumByCode("fda", Example2StatusEnum.class);
System.out.println("quotaStatusEnum12 = " + quotaStatusEnum22);
}
为了方便查看效果,可以在最后打个断点。
查看结果,发现和预期一样
拓展
假设,可能需要根据description
获取枚举,实际场景可能遇不到,重点在于思想。
那么几种解决方案:
- 在原有的BaseEnum接口上加一个String getDescription(),然后MyEnumUtil 中添加一个和toEnumByCode类似的方法,泛型中依然使用BaseEnum。
- 新建一个新接口BaseDescEnum,里面就一个String getDescription()方法。然后MyEnumUtil 中添加一个和toEnumByCode类似的方法,泛型中使用新的BaseDescEnum。
这里我建议使用第2种方法,这样颗粒度更细。第1种就算不需要根据description
获取枚举,也要实现String getDescription方法(虽然1.8之后可以通default关键字在接口默认实现,但是个人不太建议此场景这么使用)。
下面简单说一下实现。
新增BaseDescEnum接口
package com.zdh.zdhenum;
/**
* @author dh
* @date 2024/07/23
* @desc (详细信息)
*/
public interface BaseDescEnum {
/**
* 获取description
* @return
*/
String getDescription();
}
假设仅仅Example1StatusEnum需要,代码修改如下:
package com.zdh.zdhenum;
import java.util.Objects;
/**
* @author developer_ZhangXinHua
* @date 2024/07/24
* @desc (详细信息)
*/
public enum Example1StatusEnum implements BaseEnum,BaseDescEnum{
NEW("new", "新建状态"),
FAIL("fail", "失败状态"),
SUCCESS("success", "成功状态"),
CLOSED("closed", "关闭状态");
private String code;
private String description;
Example1StatusEnum(String code, String description) {
this.code = code;
this.description = description;
}
/**
* 获取code
*
* @return
*/
@Override
public String getCode() {
return this.code;
}
/**
* 获取description
*
* @return
*/
@Override
public String getDescription() {
return this.description;
}
}
MyEnumUtil中添加如下方法
public static <E extends Enum<E> & BaseDescEnum> E toEnumByDesc(String desc, Class<E> enumClass) {
for (E enumConstant : enumClass.getEnumConstants()) {
if (Objects.equals(enumConstant.getDescription(),code)) {
return enumConstant;
}
}
return null;
}
调用
public static void main(String[] args) {
Example1StatusEnum quotaStatusEnum11 = MyEnumUtil.toEnumByCode("new", Example1StatusEnum.class);
System.out.println("quotaStatusEnum11 = " + quotaStatusEnum11);
Example1StatusEnum quotaStatusEnum12 = MyEnumUtil.toEnumByCode("processing", Example1StatusEnum.class);
System.out.println("quotaStatusEnum12 = " + quotaStatusEnum12);
Example2StatusEnum quotaStatusEnum21 = MyEnumUtil.toEnumByCode("processing", Example2StatusEnum.class);
System.out.println("quotaStatusEnum11 = " + quotaStatusEnum21);
Example2StatusEnum quotaStatusEnum22 = MyEnumUtil.toEnumByCode("fda", Example2StatusEnum.class);
System.out.println("quotaStatusEnum12 = " + quotaStatusEnum22);
Example1StatusEnum enumByDesc11 = MyEnumUtil.toEnumByDesc("新建状态", Example1StatusEnum.class);
System.out.println("enumByDesc11 = " + enumByDesc11);
Example1StatusEnum enumByDesc12 = MyEnumUtil.toEnumByDesc("xfdas", Example1StatusEnum.class);
System.out.println("enumByDesc12 = " + enumByDesc12);
// Example1StatusEnum enumByDesc13 = MyEnumUtil.toEnumByDesc("新建状态", Example2StatusEnum.class);
// System.out.println("enumByDesc13 = " + enumByDesc13);
}
发现如果Example2StatusEnum没有实现BaseDescEnum,连编译都不能通过。为什么上文不建议使用default
,这样如果别人不熟悉实现,使用我们的工具类,可以强制让使用该工具类的人员,必须通过BaseDescEnum实现进行重写getDescription,防止忘记重写getDescription,从而获取到错误的description。
正常获取。
至此,优化完成。🎉🎊