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等的引用,可以简单理解为函数指针,它是一种更加底层的查找、调整和调用方法的机制。
* 参考:
*
* interface Duck { @@ -159,7 +160,7 @@ public class MethodHandleUtil { } /** - * 执行接口或对象中的方法
+ * 执行接口或对象中的特殊方法(private、static等)
* ** interface Duck { diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java index b0f9b1d7f..6f3176433 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java @@ -344,6 +344,17 @@ public class ReflectUtil { } } + /** + * 是否为父类引用字段
+ * 当字段所在类是对象子类时(对象中定义的非static的class),会自动生成一个以"this$0"为名称的字段,指向父类对象 + * @param field 字段 + * @return 是否为父类引用字段 + * @since 5.7.20 + */ + public static boolean isOuterClassField(Field field){ + return "this$0".equals(field.getName()); + } + // --------------------------------------------------------------------------------------------------------- method /** @@ -673,11 +684,12 @@ public class ReflectUtil { * @return 是否为equals方法 */ public static boolean isEqualsMethod(Method method) { - if (method == null || false == "equals".equals(method.getName())) { + if (method == null || + 1 != method.getParameterCount() || + false == "equals".equals(method.getName())) { return false; } - final Class>[] paramTypes = method.getParameterTypes(); - return (1 == paramTypes.length && paramTypes[0] == Object.class); + return (method.getParameterTypes()[0] == Object.class); } /** @@ -712,9 +724,67 @@ public class ReflectUtil { * @since 5.1.1 */ public static boolean isEmptyParam(Method method) { - return method.getParameterTypes().length == 0; + return method.getParameterCount() == 0; } + /** + * 检查给定方法是否为Getter或者Setter方法,规则为:
+ *