mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
[新特性]反射调用支持传递参数的值为null
增加对null参数传递的支持,在传递null参数保持类型信息不丢失
This commit is contained in:
parent
f4d357971b
commit
8181519c0d
@ -0,0 +1,20 @@
|
|||||||
|
package cn.hutool.core.bean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为了解决反射过程中,需要传递null参数,但是会丢失参数类型而设立的包装类
|
||||||
|
*/
|
||||||
|
public class NullWrapperBean {
|
||||||
|
|
||||||
|
private final Class<?> mClasses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param classes null的类型
|
||||||
|
*/
|
||||||
|
public NullWrapperBean(Class<?> classes) {
|
||||||
|
this.mClasses = classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getClasses() {
|
||||||
|
return mClasses;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.core.util;
|
package cn.hutool.core.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.NullWrapperBean;
|
||||||
import cn.hutool.core.convert.BasicType;
|
import cn.hutool.core.convert.BasicType;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
@ -139,15 +140,21 @@ public class ClassUtil {
|
|||||||
* @param objects 对象数组,如果数组中存在{@code null}元素,则此元素被认为是Object类型
|
* @param objects 对象数组,如果数组中存在{@code null}元素,则此元素被认为是Object类型
|
||||||
* @return 类数组
|
* @return 类数组
|
||||||
*/
|
*/
|
||||||
public static Class<?>[] getClasses(Object... objects) {
|
public static Class<?>[] getClasses(Object... objects) {
|
||||||
Class<?>[] classes = new Class<?>[objects.length];
|
Class<?>[] classes = new Class<?>[objects.length];
|
||||||
Object obj;
|
Object obj;
|
||||||
for (int i = 0; i < objects.length; i++) {
|
for (int i = 0; i < objects.length; i++) {
|
||||||
obj = objects[i];
|
obj = objects[i];
|
||||||
classes[i] = (null == obj) ? Object.class : obj.getClass();
|
if (obj instanceof NullWrapperBean) {
|
||||||
}
|
classes[i] = ((NullWrapperBean) obj).getClasses();
|
||||||
return classes;
|
} else if (null == obj) {
|
||||||
}
|
classes[i] = Object.class;
|
||||||
|
} else {
|
||||||
|
classes[i] = obj.getClass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定类是否与给定的类名相同
|
* 指定类是否与给定的类名相同
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.core.util;
|
package cn.hutool.core.util;
|
||||||
|
|
||||||
import cn.hutool.core.annotation.Alias;
|
import cn.hutool.core.annotation.Alias;
|
||||||
|
import cn.hutool.core.bean.NullWrapperBean;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
@ -864,78 +865,84 @@ public class ReflectUtil {
|
|||||||
return invoke(obj, method, args);
|
return invoke(obj, method, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行方法
|
* 执行方法
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 对于用户传入参数会做必要检查,包括:
|
* 对于用户传入参数会做必要检查,包括:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* 1、忽略多余的参数
|
* 1、忽略多余的参数
|
||||||
* 2、参数不够补齐默认值
|
* 2、参数不够补齐默认值
|
||||||
* 3、传入参数为null,但是目标参数类型为原始类型,做转换
|
* 3、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param <T> 返回对象类型
|
* @param <T> 返回对象类型
|
||||||
* @param obj 对象,如果执行静态方法,此值为<code>null</code>
|
* @param obj 对象,如果执行静态方法,此值为<code>null</code>
|
||||||
* @param method 方法(对象方法或static方法都可)
|
* @param method 方法(对象方法或static方法都可)
|
||||||
* @param args 参数对象
|
* @param args 参数对象
|
||||||
* @return 结果
|
* @return 结果
|
||||||
* @throws UtilException 一些列异常的包装
|
* @throws UtilException 一些列异常的包装
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> T invoke(Object obj, Method method, Object... args) throws UtilException {
|
public static <T> T invoke(Object obj, Method method, Object... args) throws UtilException {
|
||||||
setAccessible(method);
|
setAccessible(method);
|
||||||
|
|
||||||
// 检查用户传入参数:
|
// 检查用户传入参数:
|
||||||
// 1、忽略多余的参数
|
// 1、忽略多余的参数
|
||||||
// 2、参数不够补齐默认值
|
// 2、参数不够补齐默认值
|
||||||
// 3、传入参数为null,但是目标参数类型为原始类型,做转换
|
// 3、通过NullWrapperBean传递的参数,会直接赋值null
|
||||||
// 4、传入参数类型不对应,尝试转换类型
|
// 4、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
// 5、传入参数类型不对应,尝试转换类型
|
||||||
final Object[] actualArgs = new Object[parameterTypes.length];
|
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||||
if (null != args) {
|
final Object[] actualArgs = new Object[parameterTypes.length];
|
||||||
for (int i = 0; i < actualArgs.length; i++) {
|
if (null != args) {
|
||||||
if (i >= args.length || null == args[i]) {
|
for (int i = 0; i < actualArgs.length; i++) {
|
||||||
// 越界或者空值
|
if (i >= args.length || null == args[i]) {
|
||||||
actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
|
// 越界或者空值
|
||||||
} else if (false == parameterTypes[i].isAssignableFrom(args[i].getClass())) {
|
actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
|
||||||
//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
|
} else if (args[i] instanceof NullWrapperBean) {
|
||||||
final Object targetValue = Convert.convert(parameterTypes[i], args[i]);
|
//如果是通过NullWrapperBean传递的null参数,直接赋值null
|
||||||
if (null != targetValue) {
|
actualArgs[i] = null;
|
||||||
actualArgs[i] = targetValue;
|
} else if (!parameterTypes[i].isAssignableFrom(args[i].getClass())) {
|
||||||
}
|
//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
|
||||||
} else {
|
final Object targetValue = Convert.convert(parameterTypes[i], args[i]);
|
||||||
actualArgs[i] = args[i];
|
if (null != targetValue) {
|
||||||
}
|
actualArgs[i] = targetValue;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
actualArgs[i] = args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs);
|
return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new UtilException(e);
|
throw new UtilException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行对象中指定方法
|
* 执行对象中指定方法
|
||||||
*
|
* 如果需要传递的参数为null,请使用NullWrapperBean来传递,不然会丢失类型信息
|
||||||
* @param <T> 返回对象类型
|
*
|
||||||
* @param obj 方法所在对象
|
* @param <T> 返回对象类型
|
||||||
* @param methodName 方法名
|
* @param obj 方法所在对象
|
||||||
* @param args 参数列表
|
* @param methodName 方法名
|
||||||
* @return 执行结果
|
* @param args 参数列表
|
||||||
* @throws UtilException IllegalAccessException包装
|
* @return 执行结果
|
||||||
* @since 3.1.2
|
* @throws UtilException IllegalAccessException包装
|
||||||
*/
|
* @see NullWrapperBean
|
||||||
public static <T> T invoke(Object obj, String methodName, Object... args) throws UtilException {
|
* @since 3.1.2
|
||||||
final Method method = getMethodOfObj(obj, methodName, args);
|
*/
|
||||||
if (null == method) {
|
public static <T> T invoke(Object obj, String methodName, Object... args) throws UtilException {
|
||||||
throw new UtilException(StrUtil.format("No such method: [{}]", methodName));
|
final Method method = getMethodOfObj(obj, methodName, args);
|
||||||
}
|
if (null == method) {
|
||||||
return invoke(obj, method, args);
|
throw new UtilException(StrUtil.format("No such method: [{}]", methodName));
|
||||||
}
|
}
|
||||||
|
return invoke(obj, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置方法为可访问(私有方法可以被外部调用)
|
* 设置方法为可访问(私有方法可以被外部调用)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user