From 80239e2f27b5b8d426d87205210a21e5a43f5600 Mon Sep 17 00:00:00 2001 From: hzd <2065413046@qq.com> Date: Thu, 3 Sep 2020 15:48:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=9A=E4=B8=BE=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/convert/EnumItem.java | 64 +++++++++++++++++++ .../core/convert/impl/EnumConverter.java | 59 +++++++++++------ 2 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/convert/EnumItem.java diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/EnumItem.java b/hutool-core/src/main/java/cn/hutool/core/convert/EnumItem.java new file mode 100644 index 000000000..f620f6ea8 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/convert/EnumItem.java @@ -0,0 +1,64 @@ +package cn.hutool.core.convert; + +import java.io.Serializable; + +/** + * + *枚举元素通用接口,在自定义枚举上实现此接口可以用于数据转换
+ *数据库保存时建议保存 intVal()而非ordinal()防备需求变更
+ * @param + */ +public interface EnumItem> 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; + } + + +} + diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/EnumConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/EnumConverter.java index 292dc04c4..634222ecf 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/EnumConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/EnumConverter.java @@ -1,6 +1,7 @@ package cn.hutool.core.convert.impl; import cn.hutool.core.convert.AbstractConverter; +import cn.hutool.core.convert.EnumItem; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.EnumUtil; @@ -52,37 +53,55 @@ public class EnumConverter extends AbstractConverter { } /** - * 尝试找到类似转换的静态方法调用实现转换 - * + * 尝试找到类似转换的静态方法调用实现转换且优先使用
+ * 约定枚举类应该提供 valueOf(String) 和 valueOf(Integer)用于转换 + * oriInt /name 转换托底 + * * @param value 被转换的值 * @param enumClass enum类 * @return 对应的枚举值 */ protected static Enum tryConvertEnum(Object value, Class enumClass) { + if(value==null) { + return null; + } Enum enumResult = null; - 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 + if(EnumItem.class.isAssignableFrom(enumClass)) { + EnumItem first = (EnumItem) EnumUtil.getEnumAt(enumClass, 0); + if(value instanceof Integer) { + return (Enum) first.fromInt((Integer) value); + }else if(value instanceof String){ + return (Enum) first.fromStr( value.toString()); } } - - // 尝试查找其它用户自定义方法 - if(null == enumResult){ - final Map, Method> valueOfMethods = getValueOfMethods(enumClass); - if (MapUtil.isNotEmpty(valueOfMethods)) { - final Class valueClass = value.getClass(); - for (Map.Entry, Method> entry : valueOfMethods.entrySet()) { - if (ClassUtil.isAssignable(entry.getKey(), valueClass)) { - enumResult = ReflectUtil.invokeStatic(entry.getValue(), value); - } + // 用户自定义方法优先, + final Map, Method> valueOfMethods = getValueOfMethods(enumClass); + if (MapUtil.isNotEmpty(valueOfMethods)) { + final Class valueClass = value.getClass(); + for (Map.Entry, Method> entry : valueOfMethods.entrySet()) { + 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; }