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 1fd44d0df..50d80525f 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
@@ -3,6 +3,7 @@ package cn.hutool.core.lang.reflect;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -42,13 +43,16 @@ public class MethodHandleUtil {
*
*
* @param callerClass 方法所在类或接口
- * @param name 方法名称
- * @param type 返回类型和参数类型
+ * @param name 方法名称,{@link null}或者空则查找构造方法
+ * @param type 返回类型和参数类型
* @return 方法句柄 {@link MethodHandle},{@code null}表示未找到方法
*/
- public static MethodHandle findMethod(Class> callerClass, String name, MethodType type){
- MethodHandle handle = null;
+ public static MethodHandle findMethod(Class> callerClass, String name, MethodType type) {
+ if (StrUtil.isBlank(name)) {
+ return findConstructor(callerClass, type);
+ }
+ MethodHandle handle = null;
final MethodHandles.Lookup lookup = lookup(callerClass);
try {
handle = lookup.findVirtual(callerClass, name, type);
@@ -57,7 +61,7 @@ public class MethodHandleUtil {
}
// static方法
- if(null == handle){
+ if (null == handle) {
try {
handle = lookup.findStatic(callerClass, name, type);
} catch (IllegalAccessException | NoSuchMethodException ignore) {
@@ -66,7 +70,7 @@ public class MethodHandleUtil {
}
// 特殊方法,包括构造方法、私有方法等
- if(null == handle){
+ if (null == handle) {
try {
handle = lookup.findSpecial(callerClass, name, type, callerClass);
} catch (NoSuchMethodException ignore) {
@@ -80,7 +84,36 @@ public class MethodHandleUtil {
}
/**
- * 执行Interface中的default方法
+ * 查找指定的构造方法
+ *
+ * @param callerClass 类
+ * @param args 参数
+ * @return 构造方法句柄
+ */
+ public static MethodHandle findConstructor(Class> callerClass, Class>... args) {
+ return findConstructor(callerClass, MethodType.methodType(void.class, args));
+ }
+
+ /**
+ * 查找指定的构造方法
+ *
+ * @param callerClass 类
+ * @param type 参数类型,此处返回类型应为void.class
+ * @return 构造方法句柄
+ */
+ public static MethodHandle findConstructor(Class> callerClass, MethodType type) {
+ final MethodHandles.Lookup lookup = lookup(callerClass);
+ try {
+ return lookup.findConstructor(callerClass, type);
+ } catch (NoSuchMethodException e) {
+ return null;
+ } catch (IllegalAccessException e) {
+ throw new UtilException(e);
+ }
+ }
+
+ /**
+ * 执行接口或对象中的方法
*
*
* interface Duck {
@@ -100,7 +133,7 @@ public class MethodHandleUtil {
* @param args 参数
* @return 结果
*/
- public static T invoke(Object obj, String methodName, Object... args) {
+ public static T invokeSpecial(Object obj, String methodName, Object... args) {
Assert.notNull(obj, "Object to get method must be not null!");
Assert.notBlank(methodName, "Method name must be not blank!");
@@ -108,11 +141,23 @@ public class MethodHandleUtil {
if (null == method) {
throw new UtilException("No such method: [{}] from [{}]", methodName, obj.getClass());
}
- return invoke(obj, method, args);
+ return invokeSpecial(obj, method, args);
}
/**
- * 执行Interface中的default方法
+ * 执行接口或对象中的方法
+ *
+ * @param obj 接口的子对象或代理对象
+ * @param method 方法
+ * @param args 参数
+ * @return 结果
+ */
+ public static T invoke(Object obj, Method method, Object... args) {
+ return invoke(false, obj, method, args);
+ }
+
+ /**
+ * 执行接口或对象中的方法
*
*
* interface Duck {
@@ -124,7 +169,32 @@ public class MethodHandleUtil {
* Duck duck = (Duck) Proxy.newProxyInstance(
* ClassLoaderUtil.getClassLoader(),
* new Class[] { Duck.class },
- * MethodHandleUtil::invokeDefault);
+ * MethodHandleUtil::invoke);
+ *
+ *
+ * @param obj 接口的子对象或代理对象
+ * @param method 方法
+ * @param args 参数
+ * @return 结果
+ */
+ public static T invokeSpecial(Object obj, Method method, Object... args) {
+ return invoke(true, obj, method, args);
+ }
+
+ /**
+ * 执行接口或对象中的方法
+ *
+ *
+ * interface Duck {
+ * default String quack() {
+ * return "Quack";
+ * }
+ * }
+ *
+ * Duck duck = (Duck) Proxy.newProxyInstance(
+ * ClassLoaderUtil.getClassLoader(),
+ * new Class[] { Duck.class },
+ * MethodHandleUtil::invoke);
*
*
* @param obj 接口的子对象或代理对象
@@ -133,13 +203,17 @@ public class MethodHandleUtil {
* @return 结果
*/
@SuppressWarnings("unchecked")
- public static T invoke(Object obj, Method method, Object... args) {
+ public static T invoke(boolean isSpecial, Object obj, Method method, Object... args) {
+ Assert.notNull(method, "Method must be not null!");
final Class> declaringClass = method.getDeclaringClass();
+ final MethodHandles.Lookup lookup = lookup(declaringClass);
try {
- return (T) lookup(declaringClass)
- .unreflectSpecial(method, declaringClass)
- .bindTo(obj)
- .invokeWithArguments(args);
+ MethodHandle handle = isSpecial ? lookup.unreflectSpecial(method, declaringClass)
+ : lookup.unreflect(method);
+ if(null != obj){
+ handle = handle.bindTo(obj);
+ }
+ return (T) handle.invokeWithArguments(args);
} catch (Throwable e) {
throw new UtilException(e);
}
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 a96fda282..39afaaaac 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
@@ -920,7 +920,7 @@ public class ReflectUtil {
if(method.isDefault()){
// 当方法是default方法时,尤其对象是代理对象,需使用句柄方式执行
// 代理对象情况下调用method.invoke会导致循环引用执行,最终栈溢出
- return MethodHandleUtil.invoke(obj, method, args);
+ return MethodHandleUtil.invokeSpecial(obj, method, args);
}
try {
diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/reflect/MethodHandleUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/reflect/MethodHandleUtilTest.java
index 2772fee10..3eb2120ae 100755
--- a/hutool-core/src/test/java/cn/hutool/core/lang/reflect/MethodHandleUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/lang/reflect/MethodHandleUtilTest.java
@@ -17,13 +17,13 @@ public class MethodHandleUtilTest {
Duck duck = (Duck) Proxy.newProxyInstance(
ClassLoaderUtil.getClassLoader(),
new Class[] { Duck.class },
- MethodHandleUtil::invoke);
+ MethodHandleUtil::invokeSpecial);
Assert.assertEquals("Quack", duck.quack());
// 测试子类执行default方法
final Method quackMethod = ReflectUtil.getMethod(Duck.class, "quack");
- String quack = MethodHandleUtil.invoke(new BigDuck(), quackMethod);
+ String quack = MethodHandleUtil.invokeSpecial(new BigDuck(), quackMethod);
Assert.assertEquals("Quack", quack);
// 测试反射执行默认方法
@@ -42,7 +42,7 @@ public class MethodHandleUtilTest {
}
@Test
- public void invokeStaticTest(){
+ public void invokeStaticByProxyTest(){
Duck duck = (Duck) Proxy.newProxyInstance(
ClassLoaderUtil.getClassLoader(),
new Class[] { Duck.class },
@@ -54,11 +54,19 @@ public class MethodHandleUtilTest {
@Test
public void invokeTest(){
// 测试执行普通方法
- final int size = MethodHandleUtil.invoke(new BigDuck(),
+ final int size = MethodHandleUtil.invokeSpecial(new BigDuck(),
ReflectUtil.getMethod(BigDuck.class, "getSize"));
Assert.assertEquals(36, size);
}
+ @Test
+ public void invokeStaticTest(){
+ // 测试执行普通方法
+ final String result = MethodHandleUtil.invoke(null,
+ ReflectUtil.getMethod(Duck.class, "getDuck", int.class), 78);
+ Assert.assertEquals("Duck 78", result);
+ }
+
@Test
public void findMethodTest() throws Throwable {
MethodHandle handle = MethodHandleUtil.findMethod(Duck.class, "quack",