diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java index 320df9254..c900eaebc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java @@ -6,6 +6,7 @@ import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.map.WeakConcurrentMap; import cn.hutool.core.reflect.LookupFactory; import cn.hutool.core.reflect.MethodUtil; +import cn.hutool.core.reflect.ModifierUtil; import cn.hutool.core.reflect.ReflectUtil; import java.io.Serializable; @@ -13,7 +14,6 @@ import java.lang.invoke.*; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -76,7 +76,7 @@ public class LambdaFactory { final MutableEntry, Executable> cacheKey = new MutableEntry<>(functionInterfaceType, executable); return (F) CACHE.computeIfAbsent(cacheKey, key -> { final List abstractMethods = Arrays.stream(functionInterfaceType.getMethods()) - .filter(m -> Modifier.isAbstract(m.getModifiers())) + .filter(ModifierUtil::isAbstract) .collect(Collectors.toList()); Assert.equals(abstractMethods.size(), 1, "不支持非函数式接口"); ReflectUtil.setAccessible(executable); diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java index c3fd98444..3777d5e69 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java @@ -10,8 +10,12 @@ import java.lang.reflect.Method; /** * {@link MethodHandles.Lookup}工厂,用于创建{@link MethodHandles.Lookup}对象
+ * {@link MethodHandles.Lookup}是一个方法句柄查找对象,用于在指定类中查找符合给定方法名称、方法类型的方法句柄。 + * + *

* jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial * 时会出现权限不够问题,抛出"no private access for invokespecial"异常,因此针对JDK8及JDK9+分别封装lookup方法。 + *

* *

* 参考: diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java index a0bad42b4..791e423dd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java @@ -12,9 +12,15 @@ import java.lang.reflect.Method; /** * 方法句柄{@link MethodHandle}封装工具类
* 方法句柄是一个有类型的,可以直接执行的指向底层方法、构造器、field等的引用,可以简单理解为函数指针,它是一种更加底层的查找、调整和调用方法的机制。 + * + *

+ * {@link MethodHandle}类似于C/C++的函数指针,用于模拟在字节码层次的方法调用,且可以采用字节码优化,优于反射。 + *

+ *

* 参考: *

* * @author looly @@ -33,7 +39,7 @@ public class MethodHandleUtil { * * @param callerClass 方法所在类或接口 * @param name 方法名称,{@code null}或者空则查找构造方法 - * @param type 返回类型和参数类型 + * @param type 返回类型和参数类型,可以使用{@code MethodType#methodType}构建 * @return 方法句柄 {@link MethodHandle},{@code null}表示未找到方法 */ public static MethodHandle findMethod(final Class callerClass, final String name, final MethodType type) { @@ -101,6 +107,36 @@ public class MethodHandleUtil { } } + /** + * 执行方法句柄,{@link MethodHandle#invoke(Object...)}包装
+ * + * @param methodHandle {@link MethodHandle} + * @param args 方法参数值,支持子类转换和自动拆装箱 + * @param 返回值类型 + * @return 方法返回值 + */ + @SuppressWarnings("unchecked") + public static T invokeHandle(final MethodHandle methodHandle, final Object... args) { + try { + return (T) methodHandle.invoke(args); + } catch (final Throwable e) { + throw new RuntimeException(e); + } + } + + /** + * 执行接口或对象中的方法 + * + * @param 返回结果类型 + * @param obj 接口的子对象或代理对象 + * @param method 方法 + * @param args 参数 + * @return 结果 + */ + public static T invoke(final Object obj, final Method method, final Object... args) { + return invoke(false, obj, method, args); + } + /** * 执行接口或对象中的特殊方法(private、static等)
* @@ -133,19 +169,6 @@ public class MethodHandleUtil { return invokeSpecial(obj, method, args); } - /** - * 执行接口或对象中的方法 - * - * @param 返回结果类型 - * @param obj 接口的子对象或代理对象 - * @param method 方法 - * @param args 参数 - * @return 结果 - */ - public static T invoke(final Object obj, final Method method, final Object... args) { - return invoke(false, obj, method, args); - } - /** * 执行接口或对象中的特殊方法(private、static等)
* diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java index b2ebfc722..08b39f019 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java @@ -127,7 +127,7 @@ public class ModifierUtil { * @return 是否是Public */ public static boolean isPublic(final Member member) { - return hasModifier(member, ModifierType.PUBLIC); + return Modifier.isPublic(member.getModifiers()); } /** @@ -137,7 +137,7 @@ public class ModifierUtil { * @return 是否是Public */ public static boolean isPublic(final Class clazz) { - return hasModifier(clazz, ModifierType.PUBLIC); + return Modifier.isPublic(clazz.getModifiers()); } /** @@ -148,7 +148,7 @@ public class ModifierUtil { * @since 4.0.8 */ public static boolean isStatic(final Member member) { - return hasModifier(member, ModifierType.STATIC); + return Modifier.isStatic(member.getModifiers()); } /** @@ -159,7 +159,7 @@ public class ModifierUtil { * @since 4.0.8 */ public static boolean isStatic(final Class clazz) { - return hasModifier(clazz, ModifierType.STATIC); + return Modifier.isStatic(clazz.getModifiers()); } /** @@ -192,7 +192,7 @@ public class ModifierUtil { * @since 5.7.23 */ public static boolean isAbstract(final Member member) { - return hasModifier(member, ModifierType.ABSTRACT); + return Modifier.isAbstract(member.getModifiers()); } /** @@ -203,7 +203,7 @@ public class ModifierUtil { * @since 5.7.23 */ public static boolean isAbstract(final Class clazz) { - return hasModifier(clazz, ModifierType.ABSTRACT); + return Modifier.isAbstract(clazz.getModifiers()); } /** @@ -251,9 +251,7 @@ public class ModifierUtil { } //将字段的访问权限设为true:即去除private修饰符的影响 - if (false == field.isAccessible()) { - field.setAccessible(true); - } + ReflectUtil.setAccessible(field); try { //去除final修饰符的影响,将字段设为可修改的 final Field modifiersField = Field.class.getDeclaredField("modifiers");