diff --git a/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java b/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java new file mode 100644 index 000000000..0d2486471 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java @@ -0,0 +1,33 @@ +package cn.hutool.core.exceptions; + +/** + * InvocationTargetException的运行时异常 + * + * @author looly + */ +public class InvocationTargetRuntimeException extends UtilException { + + public InvocationTargetRuntimeException(final Throwable e) { + super(e); + } + + public InvocationTargetRuntimeException(final String message) { + super(message); + } + + public InvocationTargetRuntimeException(final String messageTemplate, final Object... params) { + super(messageTemplate, params); + } + + public InvocationTargetRuntimeException(final String message, final Throwable throwable) { + super(message, throwable); + } + + public InvocationTargetRuntimeException(final String message, final Throwable throwable, final boolean enableSuppression, final boolean writableStackTrace) { + super(message, throwable, enableSuppression, writableStackTrace); + } + + public InvocationTargetRuntimeException(final Throwable throwable, final String messageTemplate, final Object... params) { + super(throwable, messageTemplate, params); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index f7c5f1352..d91532038 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -1097,7 +1097,7 @@ public class FileUtil extends PathUtil { * 情况如下: * *
-	 * 1、src和dest都为目录,则讲src下所有文件目录拷贝到dest下
+	 * 1、src和dest都为目录,则将src下所有文件目录拷贝到dest下
 	 * 2、src和dest都为文件,直接复制,名字为dest
 	 * 3、src为文件,dest为目录,将src拷贝到dest目录下
 	 * 
@@ -1117,7 +1117,7 @@ public class FileUtil extends PathUtil { * 情况如下: * *
-	 * 1、src和dest都为目录,则讲src下所有文件(包括子目录)拷贝到dest下
+	 * 1、src和dest都为目录,则将src下所有文件(包括子目录)拷贝到dest下
 	 * 2、src和dest都为文件,直接复制,名字为dest
 	 * 3、src为文件,dest为目录,将src拷贝到dest目录下
 	 * 
diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodUtil.java index b617e8acf..ee769dab6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.classloader.ClassLoaderUtil; import cn.hutool.core.collection.SetUtil; import cn.hutool.core.collection.UniqueKeySet; import cn.hutool.core.convert.Convert; +import cn.hutool.core.exceptions.InvocationTargetRuntimeException; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Singleton; @@ -13,6 +14,7 @@ import cn.hutool.core.map.WeakConcurrentMap; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -536,37 +538,39 @@ public class MethodUtil { * @return 结果 * @throws UtilException 一些列异常的包装 */ - @SuppressWarnings("unchecked") public static T invoke(final Object obj, final Method method, final Object... args) throws UtilException { - ReflectUtil.setAccessible(method); - - // 检查用户传入参数: - // 1、忽略多余的参数 - // 2、参数不够补齐默认值 - // 3、通过NullWrapperBean传递的参数,会直接赋值null - // 4、传入参数为null,但是目标参数类型为原始类型,做转换 - // 5、传入参数类型不对应,尝试转换类型 - final Class[] parameterTypes = method.getParameterTypes(); - final Object[] actualArgs = new Object[parameterTypes.length]; - if (null != args) { - for (int i = 0; i < actualArgs.length; i++) { - if (i >= args.length || null == args[i]) { - // 越界或者空值 - actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]); - } else if (args[i] instanceof NullWrapperBean) { - //如果是通过NullWrapperBean传递的null参数,直接赋值null - actualArgs[i] = null; - } else if (false == parameterTypes[i].isAssignableFrom(args[i].getClass())) { - //对于类型不同的字段,尝试转换,转换失败则使用原对象类型 - final Object targetValue = Convert.convert(parameterTypes[i], args[i]); - if (null != targetValue) { - actualArgs[i] = targetValue; - } - } else { - actualArgs[i] = args[i]; - } - } + try { + return invokeRaw(obj, method, args); + } catch (final InvocationTargetException e) { + throw new InvocationTargetRuntimeException(e); + } catch (final IllegalAccessException e) { + throw new UtilException(e); } + } + + /** + * 执行方法 + * + *

+ * 对于用户传入参数会做必要检查,包括: + * + *

+	 *     1、忽略多余的参数
+	 *     2、参数不够补齐默认值
+	 *     3、传入参数为null,但是目标参数类型为原始类型,做转换
+	 * 
+ * + * @param 返回对象类型 + * @param obj 对象,如果执行静态方法,此值为{@code null} + * @param method 方法(对象方法或static方法都可) + * @param args 参数对象 + * @return 结果 + * @throws InvocationTargetRuntimeException 目标方法执行异常 + * @throws IllegalAccessException 访问权限异常 + */ + @SuppressWarnings("unchecked") + public static T invokeRaw(final Object obj, final Method method, final Object... args) throws InvocationTargetException, IllegalAccessException { + ReflectUtil.setAccessible(method); if (method.isDefault()) { // 当方法是default方法时,尤其对象是代理对象,需使用句柄方式执行 @@ -574,11 +578,7 @@ public class MethodUtil { return MethodHandleUtil.invokeSpecial(obj, method, args); } - try { - return (T) method.invoke(ModifierUtil.isStatic(method) ? null : obj, actualArgs); - } catch (final Exception e) { - throw new UtilException(e); - } + return (T) method.invoke(ModifierUtil.isStatic(method) ? null : obj, actualArgs(method, args)); } /** @@ -737,4 +737,44 @@ public class MethodUtil { } return result; } + + /** + * 检查用户传入参数: + *
    + *
  • 1、忽略多余的参数
  • + *
  • 2、参数不够补齐默认值
  • + *
  • 3、通过NullWrapperBean传递的参数,会直接赋值null
  • + *
  • 4、传入参数为null,但是目标参数类型为原始类型,做转换
  • + *
  • 5、传入参数类型不对应,尝试转换类型
  • + *
+ * + * @param method 方法 + * @param args 参数 + * @return 实际的参数数组 + */ + private static Object[] actualArgs(final Method method, final Object[] args) { + final Class[] parameterTypes = method.getParameterTypes(); + final Object[] actualArgs = new Object[parameterTypes.length]; + if (null != args) { + for (int i = 0; i < actualArgs.length; i++) { + if (i >= args.length || null == args[i]) { + // 越界或者空值 + actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]); + } else if (args[i] instanceof NullWrapperBean) { + //如果是通过NullWrapperBean传递的null参数,直接赋值null + actualArgs[i] = null; + } else if (false == parameterTypes[i].isAssignableFrom(args[i].getClass())) { + //对于类型不同的字段,尝试转换,转换失败则使用原对象类型 + final Object targetValue = Convert.convert(parameterTypes[i], args[i]); + if (null != targetValue) { + actualArgs[i] = targetValue; + } + } else { + actualArgs[i] = args[i]; + } + } + } + + return actualArgs; + } }