在代码中,经常用到枚举,也经常用到枚举获取code,获取type,通常我们写的代码如下:
public enum Status{
/**
*
*/
YES(1,"是"),
NO(2,"否")
;
private int code;
private String msg;
Status(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return this.code;
}
public String getMsg() {
return this.msg;
}
public static Optional<Status> of(int code) {
for (Status value : values()) {
if (Objects.equals(value.getCode(),code)){
return Optional.of(value);
}
}
return Optional.empty();
}
}
要根据某个code,得到枚举以及对应的msg,调用of()
方法。但是这样的话每个枚举都得写一边,代码行数还不少。不简洁
一开始的优化,就是写了个接口如下:
public interface IEntityEnum {
public int getCode();
public String getMsg();
}
然后枚举实现这个接口,相当于一个标准能保证枚举类都能有这样的of方法可以用。但是实际问题还是没解决,代码在每个枚举都要复制。
其实这个也不难想,把这些of方法通通抽取出去在一个工具类中,采用泛型
来匹配各种枚举类,但是问题在于,怎么调用values
方法呢?怎么告诉编译器我这个方法需要的是一个枚举,我要调用它的values方法,毕竟其他类又没这个静态方法。直到我无意发现了getEnumConstants
方法,它是Object类里的。
它的介绍:
an array containing the values comprising the enum class represented by this Class object in the order they’re declared, or null if this Class object does not represent an enum type
一个数组,其中包含组成此 Class 对象表示的枚举类的值,按声明的顺序排列;如果此 Class 对象不表示枚举类型,则为 null
因此工具类就好写了:
import cn.hutool.core.util.StrUtil;
import java.util.Optional;
/**
* EnumsUtil
*
* @author zgd
* @date 2022/8/9 17:44
*/
public class EnumsUtil {
public static <T extends IEntityEnum> Optional<T> of(int code, Class<T> cla) {
T[] enums = cla.getEnumConstants();
for (T value : enums) {
if (code == value.getCode()){
return Optional.of(value);
}
}
return Optional.empty();
}
public static <T extends IEntityEnum> String ofMsg(int code, Class<T> cla) {
Optional<T> of = of(code,cla);
return of.isPresent() ? of.get().getMsg() : "";
}
public static <T extends IEntityEnum> Integer ofCode(String msg, Class<T> cla) {
if (StrUtil.isEmpty(msg)){
return null;
}
T[] enums = cla.getEnumConstants();
for (T value : enums) {
if (msg.equals(value.getMsg())){
return value.getCode();
}
}
return null;
}
/**
* 可以试下效果
*/
public static void main(String[] args) {
System.out.println(EnumsUtil.ofMsg(1, SourceEnum.class));
System.out.println(EnumsUtil.ofMsg(2, SourceEnum.class));
}
}
用了一天后发现一个问题, 接口IEntityEnum
写死了int code和String msg, 那如果有时候code我们需要String类型,这个场景也很常见.
因此再往上包装一层
/**
* IEnum
*
* @author zgd
* @date 2022/8/10 18:09
*/
public interface IEnum<T,E> {
public T getCode();
public E getMsg();
}
public interface IEntityEnum extends IEnum<Integer,String> {
public Integer getCode();
public String getMsg();
}
import cn.hutool.core.util.StrUtil;
import java.util.Optional;
/**
* EnumsUtil
*
* @author zgd
* @date 2022/8/9 17:44
*/
public class EnumsUtil {
public static <E,V,T extends IEnum<E,V>> Optional<T> of(E code, Class<T> cla) {
T[] enums = cla.getEnumConstants();
for (T value : enums) {
if (code == value.getCode()){
return Optional.of(value);
}
}
return Optional.empty();
}
public static <E,V,T extends IEnum<E,V>> V ofMsg(E code, Class<T> cla) {
Optional<T> of = of(code,cla);
return of.map(IEnum::getMsg).orElse(null);
}
public static <E,V,T extends IEnum<E,V>> E ofCode(String msg, Class<T> cla) {
if (StrUtil.isEmpty(msg)){
return null;
}
T[] enums = cla.getEnumConstants();
for (T value : enums) {
if (msg.equals(value.getMsg())){
return value.getCode();
}
}
return null;
}
public static void main(String[] args) {
System.out.println(EnumsUtil.ofMsg("YES", TypeEnum.class));
}
}
IEntityEnum
,直接实现它的父接口 /**
* TypeEnum
*
* @author zgd
* @date 2022/8/10 18:41
*/
public enum TypeEnum implements IEnum<String,String> {
/**
*
*/
YES("YES","是"),
NO("NO","否"),
;
private String code;
private String msg;
TypeEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public String getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
}