添加枚举转换方式

This commit is contained in:
hzd 2020-09-03 15:48:43 +08:00
parent f142630fea
commit 80239e2f27
2 changed files with 103 additions and 20 deletions

View File

@ -0,0 +1,64 @@
package cn.hutool.core.convert;
import java.io.Serializable;
/**
*
*枚举元素通用接口在自定义枚举上实现此接口可以用于数据转换<br>
*数据库保存时建议保存 intVal()而非ordinal()防备需求变更<br>
* @param <E>
*/
public interface EnumItem<E extends EnumItem<E>> extends Serializable{
String name();
/**
* 在中文语境下多数时间枚举会配合一个中文说明
*/
default String text() {
return name();
}
int intVal();
@SuppressWarnings("unchecked")
default E[] items() {
return (E[]) this.getClass().getEnumConstants();
}
/**
* 通过int类型值查找兄弟其他枚举
* @param intVal
* @return
*/
default E fromInt(Integer intVal) {
if(intVal==null) {
return null;
}
E[] vs = items();
for (E enumItem : vs) {
if(enumItem.intVal()==intVal.intValue()) {
return enumItem;
}
}
return null;
}
/**
* 通过String类型的值转换根据实现可以用name/text
* @param intVal
* @return
*/
default E fromStr(String strVal) {
if(strVal==null) {
return null;
}
E[] vs = items();
for (E enumItem : vs) {
if(strVal.equalsIgnoreCase(enumItem.name())) {
return enumItem;
}
}
return null;
}
}

View File

@ -1,6 +1,7 @@
package cn.hutool.core.convert.impl; package cn.hutool.core.convert.impl;
import cn.hutool.core.convert.AbstractConverter; import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.convert.EnumItem;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.EnumUtil;
@ -52,37 +53,55 @@ public class EnumConverter extends AbstractConverter<Object> {
} }
/** /**
* 尝试找到类似转换的静态方法调用实现转换 * 尝试找到类似转换的静态方法调用实现转换且优先使用<br>
* * 约定枚举类应该提供 valueOf(String) valueOf(Integer)用于转换
* oriInt /name 转换托底
*
* @param value 被转换的值 * @param value 被转换的值
* @param enumClass enum类 * @param enumClass enum类
* @return 对应的枚举值 * @return 对应的枚举值
*/ */
protected static Enum tryConvertEnum(Object value, Class enumClass) { protected static Enum tryConvertEnum(Object value, Class enumClass) {
if(value==null) {
return null;
}
Enum enumResult = null; Enum enumResult = null;
if (value instanceof Integer) { if(EnumItem.class.isAssignableFrom(enumClass)) {
enumResult = EnumUtil.getEnumAt(enumClass, (Integer)value); EnumItem first = (EnumItem) EnumUtil.getEnumAt(enumClass, 0);
} else if (value instanceof String) { if(value instanceof Integer) {
try { return (Enum) first.fromInt((Integer) value);
enumResult = Enum.valueOf(enumClass, (String) value); }else if(value instanceof String){
} catch (IllegalArgumentException e) { return (Enum) first.fromStr( value.toString());
//ignore
} }
} }
// 用户自定义方法优先
// 尝试查找其它用户自定义方法 final Map<Class<?>, Method> valueOfMethods = getValueOfMethods(enumClass);
if(null == enumResult){ if (MapUtil.isNotEmpty(valueOfMethods)) {
final Map<Class<?>, Method> valueOfMethods = getValueOfMethods(enumClass); final Class<?> valueClass = value.getClass();
if (MapUtil.isNotEmpty(valueOfMethods)) { for (Map.Entry<Class<?>, Method> entry : valueOfMethods.entrySet()) {
final Class<?> valueClass = value.getClass(); if (ClassUtil.isAssignable(entry.getKey(), valueClass)) {
for (Map.Entry<Class<?>, Method> entry : valueOfMethods.entrySet()) { enumResult = ReflectUtil.invokeStatic(entry.getValue(), value);
if (ClassUtil.isAssignable(entry.getKey(), valueClass)) { }
enumResult = ReflectUtil.invokeStatic(entry.getValue(), value); }
} }
//oriInt 应该滞后使用 GB/T 2261.1-2003 性别编码为例对应整数并非连续数字会导致数字转枚举时失败
//0 - 未知的性别
//1 - 男性
//2 - 女性
//5 - 女性改()为男性
//6 - 男性改()为女性
//9 - 未说明的性别
if(null == enumResult){
if (value instanceof Integer) {
enumResult = EnumUtil.getEnumAt(enumClass, (Integer)value);
} else if (value instanceof String) {
try {
enumResult = Enum.valueOf(enumClass, (String) value);
} catch (IllegalArgumentException e) {
//ignore
} }
} }
} }
return enumResult; return enumResult;
} }