diff --git a/CHANGELOG.md b/CHANGELOG.md index 95e774205..aba46ae03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ------------------------------------------------------------------------------------------------------------- -# 5.7.20 (2022-01-07) +# 5.7.20 (2022-01-08) ### 🐣新特性 ### 🐞Bug修复 +* 【core 】 修复setter重载导致匹配错误(issue#2082@Github) ------------------------------------------------------------------------------------------------------------- # 5.7.19 (2022-01-07) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java index 65411b497..976f40d29 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java @@ -140,14 +140,12 @@ public class BeanDesc implements Serializable { * @return this */ private BeanDesc init() { - final Method[] methods = ReflectUtil.getMethods(this.beanClass); + final Method[] gettersAndSetters = ReflectUtil.getMethods(this.beanClass, ReflectUtil::isGetterOrSetterIgnoreCase); PropDesc prop; for (Field field : ReflectUtil.getFields(this.beanClass)) { - if (false == ModifierUtil.isStatic(field) && - // 排除对象子类 - false == "this$0".equals(field.getName())) { - //只针对非static属性 - prop = createProp(field, methods); + // 排除静态属性和对象子类 + if (false == ModifierUtil.isStatic(field) && false == ReflectUtil.isOuterClassField(field)) { + prop = createProp(field, gettersAndSetters); // 只有不存在时才放入,防止父类属性覆盖子类属性 this.propMap.putIfAbsent(prop.getFieldName(), prop); } @@ -190,12 +188,12 @@ public class BeanDesc implements Serializable { /** * 查找字段对应的Getter和Setter方法 * - * @param field 字段 - * @param methods 类中所有的方法 - * @param ignoreCase 是否忽略大小写匹配 + * @param field 字段 + * @param gettersOrSetters 类中所有的Getter或Setter方法 + * @param ignoreCase 是否忽略大小写匹配 * @return PropDesc */ - private PropDesc findProp(Field field, Method[] methods, boolean ignoreCase) { + private PropDesc findProp(Field field, Method[] gettersOrSetters, boolean ignoreCase) { final String fieldName = field.getName(); final Class fieldType = field.getType(); final boolean isBooleanField = BooleanUtil.isBoolean(fieldType); @@ -203,24 +201,19 @@ public class BeanDesc implements Serializable { Method getter = null; Method setter = null; String methodName; - Class[] parameterTypes; - for (Method method : methods) { - parameterTypes = method.getParameterTypes(); - if (parameterTypes.length > 1) { - // 多于1个参数说明非Getter或Setter - continue; - } - + for (Method method : gettersOrSetters) { methodName = method.getName(); - if (parameterTypes.length == 0) { + if (method.getParameterCount() == 0) { // 无参数,可能为Getter方法 if (isMatchGetter(methodName, fieldName, isBooleanField, ignoreCase)) { // 方法名与字段名匹配,则为Getter方法 getter = method; } } else if (isMatchSetter(methodName, fieldName, isBooleanField, ignoreCase)) { - // 只有一个参数的情况下方法名与字段名对应匹配,则为Setter方法 - setter = method; + // setter方法的参数类型和字段类型必须一致,或参数类型是字段类型的子类 + if(fieldType.isAssignableFrom(method.getParameterTypes()[0])){ + setter = method; + } } if (null != getter && null != setter) { // 如果Getter和Setter方法都找到了,不再继续寻找 @@ -261,15 +254,6 @@ public class BeanDesc implements Serializable { handledFieldName = StrUtil.upperFirst(fieldName); } - if (false == methodName.startsWith("get") && false == methodName.startsWith("is")) { - // 非标准Getter方法 - return false; - } - if ("getclass".equals(methodName)) { - //跳过getClass方法 - return false; - } - // 针对Boolean类型特殊检查 if (isBooleanField) { if (fieldName.startsWith("is")) { diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java index 796124648..d9452cd14 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -88,9 +88,8 @@ public class BeanUtil { */ public static boolean hasSetter(Class clazz) { if (ClassUtil.isNormalClass(clazz)) { - final Method[] methods = clazz.getMethods(); - for (Method method : methods) { - if (method.getParameterTypes().length == 1 && method.getName().startsWith("set")) { + for (Method method : clazz.getMethods()) { + if (method.getParameterCount() == 1 && method.getName().startsWith("set")) { // 检测包含标准的setXXX方法即视为标准的JavaBean return true; } @@ -110,7 +109,7 @@ public class BeanUtil { public static boolean hasGetter(Class clazz) { if (ClassUtil.isNormalClass(clazz)) { for (Method method : clazz.getMethods()) { - if (method.getParameterTypes().length == 0) { + if (method.getParameterCount() == 0) { if (method.getName().startsWith("get") || method.getName().startsWith("is")) { return true; } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java index 781208744..fbfa2ded3 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java @@ -12,6 +12,7 @@ import java.lang.reflect.Method; /** * 方法句柄{@link MethodHandle}封装工具类
+ * 方法句柄是一个有类型的,可以直接执行的指向底层方法、构造器、field等的引用,可以简单理解为函数指针,它是一种更加底层的查找、调整和调用方法的机制。 * 参考: *