前言
讲真的,Java的枚举类提供的方法太少了,Enum只有两个valueOf可以搞,如果碰上需要传入枚举类型的值,获取枚举类对象或者枚举类型名称的时候,只能干瞪眼,或者循环比对。最近项目就遇到这种,而且感觉以后以及别人都不会少遇到,所以就写了个帮助类,希望以后能用上吧。
反射机制
/**
* 反射方式调用enum的方法
*
* @param targetEnumClazz 枚举类的class
* @param methodName 方法
* @param parameterTypes
* @param args
*/
public static Object invoke(Class targetEnumClazz, String methodName, Class<?> parameterTypes, Object... args) throws Exception {
Method method;
if (parameterTypes != null) {
method = targetEnumClazz.getDeclaredMethod(methodName, parameterTypes);
} else {
method = targetEnumClazz.getDeclaredMethod(methodName);
}
Object[] oo = targetEnumClazz.getEnumConstants();
return method.invoke((oo[0]), args);
}
这个帮助类是基于以下枚举类的类型提供的。注意:严格限定为有typeName和typeCode的枚举类,如定义枚举类型为 ADMIN(typeName,typeCode)这种
public interface BaseCommonEnum {
/**
* 获取参数name
*
* @return 枚举value
*/
String getTypeName();
/**
* 获取 枚举key
*
* @return 枚举key
*/
String getTypeCode();
/**
* 获取全部的枚举值
*
* @return 枚举值
*/
List<Map<String, String>> getEnum();
/**
* 通过key获取枚举
*
* @param typeCode 枚举参数code
* @return 返回枚举
*/
BaseCommonEnum getEnumByTypeCode(String typeCode);
/**
* 通过value获取枚举
*
* @param typeName 枚举参数name
* @return 返回枚举
*/
BaseCommonEnum getEnumByTypeName(String typeName);
}
继承BaseCommonEnum基类定义真正的枚举类 UserSexEnum
public enum UserSexEnum implements BaseCommonEnum {
/**
*
*/
male("0", "男"),
female("1", "女"),
unknown("-1", "未知");
private String typeCode;
private String typeName;
UserSexEnum(String typeCode, String typeName) {
this.typeCode = typeCode;
this.typeName = typeName;
}
/**
* 获取枚举value
*
* @return 枚举value
*/
@Override
public String getTypeName() {
return typeName;
}
/**
* 获取 枚举key
*
* @return 枚举key
*/
@Override
public String getTypeCode() {
return typeCode;
}
@Override
public List<Map<String, String>> getEnum() {
EnumSet<UserSexEnum> all = EnumSet.allOf(UserSexEnum.class);
List<Map<String, String>> resultList = new ArrayList<>();
all.stream().forEach(e -> {
Map<String, String> eMap = new HashMap<>();
eMap.put("typeCode", e.getTypeCode());
eMap.put("typeName", e.getTypeName());
resultList.add(eMap);
});
return resultList;
}
@Override
public UserSexEnum getEnumByTypeCode(String typeCode) {
Objects.requireNonNull(typeCode);
EnumSet<UserSexEnum> all = EnumSet.allOf(UserSexEnum.class);
return all.stream().filter(e -> e.getTypeCode().equals(typeCode)).findFirst().orElse(null);
}
@Override
public UserSexEnum getEnumByTypeName(String typeName) {
Objects.requireNonNull(typeName);
EnumSet<UserSexEnum> all = EnumSet.allOf(UserSexEnum.class);
return all.stream().filter(e -> e.getTypeName().equals(typeName)).findFirst().orElse(null);
}
}
反射机制需要每个枚举类都要实现getEnum、getEnumByTypeCode、getEnumByTypeName,在实际中,我们不可能只用一个枚举类,随着业务需求以及功能需求,需要用到的枚举类也会越来越多,每个枚举类都要有上述三个方法,代码重复率随之增高。那么有没有什么简单的方法呢,那就继续往下看。
Java
首先定义一个枚举类,如下所示。注意:严格限定为有typeName和typeCode的枚举类,如定义枚举类型为 ADMIN(typeName,typeCode)这种。
public enum UserSexEnum {
/**
*
*/
male("0", "男"),
female("1", "女"),
unknown("-1", "未知");
private String typeCode;
private String typeName;
UserSexEnum(String typeCode, String typeName) {
this.typeCode = typeCode;
this.typeName = typeName;
}
/**
* 获取枚举value
*
* @return 枚举value
*/
@Override
public String getTypeName() {
return typeName;
}
/**
* 获取 枚举key
*
* @return 枚举key
*/
@Override
public String getTypeCode() {
return typeCode;
}
}
帮助类的内容:
public final class EnumHelperUtil {
/**
* 枚举转List格式
*
* @param targetEnumClazz 目标枚举Clazz
*/
public static List<Map<String, Object>> toMapList(Class targetEnumClazz) throws IllegalAccessException {
//获取方法
Method[] methods = targetEnumClazz.getMethods();
Field[] fields = targetEnumClazz.getDeclaredFields();
List<Field> fieldList = new ArrayList();
for (Method method : methods) {
for (Field field : fields) {
if (method.getName().endsWith(StringUtils.capitalize(field.getName()))) {
fieldList.add(field);
}
}
}
List<Map<String, Object>> resultList = new ArrayList();
//获取值
Enum[] enums = (Enum[]) targetEnumClazz.getEnumConstants();
Object value = null;
for (Enum e : enums) {
Map<String, Object> eMap = new HashMap();
String enumNameValue = e.name();
for (Field field : fieldList) {
// 对于private的属性,如果不解锁,那么将无法访问,会报错
field.setAccessible(true);
// 通过反射的字段获取实体中的值
value = field.get(e);
eMap.put(field.getName(), value);
}
resultList.add(eMap);
}
return resultList;
}
/**
* 通过枚举key获取对应的枚举值
*
* @param targetEnumClazz 目标枚举Clazz
* @param typeCode 对应的枚举值
*/
public static String enumExplain(Class targetEnumClazz, String typeCode) throws IllegalAccessException {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
for (Map map : list) {
if (map.get("typeCode").toString().equals(typeCode)) {
return map.get("typeName").toString();
}
}
return "";
}
}
我们也可以利用Java 8+版本的EnumSet
public final class EnumHelperUtil {
/**
* 获取字典
*
* @param targetEnumClazz
* @param <E>
* @return
*/
public static <E extends Enum<E> & BaseCommonEnum> List<Map<String, String>> getEnum(Class<E> targetEnumClazz) {
EnumSet<E> all = EnumSet.allOf(targetEnumClazz);
List<Map<String, String>> resultList = new ArrayList<>();
all.stream().forEach(e -> {
Map<String, String> eMap = new HashMap<>();
eMap.put("typeCode", e.getTypeCode());
eMap.put("typeName", e.getTypeName());
resultList.add(eMap);
});
return resultList;
}
/**
* 通过枚举类型对应的typeCode获取枚举类型
*
* @param typeCode
* @param clazz 枚举类的class
* @param <E>
* @return
*/
public static <E extends Enum<E> & BaseCommonEnum> E getEnumByKey(String typeCode, Class<E> clazz) {
Objects.requireNonNull(typeCode);
EnumSet<E> all = EnumSet.allOf(clazz);
return all.stream().filter(e -> e.getTypeCode().equals(typeCode)).findFirst().orElse(null);
}
/**
* 通过字典value获取枚举类型
*
* @param typeName
* @param clazz 枚举类的class
* @param <E>
* @return
*/
public static <E extends Enum<E> & BaseCommonEnum> E getEnumByTypeName(String typeName, Class<E> clazz) {
Objects.requireNonNull(typeName);
EnumSet<E> all = EnumSet.allOf(clazz);
return all.stream().filter(e -> e.getTypeName().equals(typeName)).findFirst().orElse(null);
}
}