diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java index 6c1769892..139016b1e 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java @@ -82,52 +82,57 @@ public class LambdaFactory { } /** - * 根据提供的方法或构造对象,构建对应的Lambda函数
+ * 根据提供的方法或构造对象,构建对应的Lambda函数,即通过Lambda函数代理方法或构造
* 调用函数相当于执行对应的方法或构造 * - * @param funcType 接受Lambda的函数式接口类型 - * @param executable 方法对象,支持构造器 - * @param Function类型 + * @param funcType 接受Lambda的函数式接口类型 + * @param executable 方法对象,支持构造器 + * @param Function类型 * @return 接受Lambda的函数式接口对象 */ @SuppressWarnings("unchecked") private static F doBuildWithoutCache(final Class funcType, final Executable executable) { ReflectUtil.setAccessible(executable); + // 获取Lambda函数 + final Method[] abstractMethods = MethodUtil.getPublicMethods(funcType, ModifierUtil::isAbstract); + Assert.equals(abstractMethods.length, 1, "不支持非函数式接口"); + + final Method invokeMethod = abstractMethods[0]; try { - return (F) metaFactory(funcType, executable).getTarget().invoke(); + return (F) metaFactory(funcType, invokeMethod, executable) + .getTarget().invoke(); } catch (final Throwable e) { throw new HutoolException(e); } } /** - * 使用给定的函数接口,代理指定方法或构造 + * 通过Lambda函数代理方法或构造 * - * @param functionInterfaceType 函数接口 - * @param executable 方法或构造 - * @return 函数锚点 + * @param funcType 函数类型 + * @param invokeMethod 函数执行的方法 + * @param executable 被代理的方法或构造 + * @return {@link CallSite} * @throws LambdaConversionException 权限等异常 */ - private static CallSite metaFactory(final Class functionInterfaceType, final Executable executable) throws LambdaConversionException { - // 被代理的方法 - final Method[] abstractMethods = MethodUtil.getPublicMethods(functionInterfaceType, ModifierUtil::isAbstract); - Assert.equals(abstractMethods.length, 1, "Class is not a functional interface."); - - final Method invokeMethod = abstractMethods[0]; - final MethodHandle methodHandle = LookupUtil.unreflect(executable); - final MethodHandles.Lookup caller = LookupUtil.lookup(); + private static CallSite metaFactory(final Class funcType, final Method invokeMethod, + final Executable executable) throws LambdaConversionException { + final MethodHandles.Lookup caller = LookupUtil.lookup(executable.getDeclaringClass()); final String invokeName = invokeMethod.getName(); - final MethodType invokedType = MethodType.methodType(functionInterfaceType); - final MethodType samMethodType = MethodType.methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes()); + final MethodType invokedType = MethodType.methodType(funcType); - if(ClassUtil.isSerializable(functionInterfaceType)){ + // 对入参做检查,原始类型转换为包装类型 + final Class[] paramTypes = invokeMethod.getParameterTypes(); + final MethodType samMethodType = MethodType.methodType(invokeMethod.getReturnType(), paramTypes); + + if (ClassUtil.isSerializable(funcType)) { return LambdaMetafactory.altMetafactory( caller, invokeName, invokedType, samMethodType, - methodHandle, + LookupUtil.unreflect(executable), MethodTypeUtil.methodType(executable), LambdaMetafactory.FLAG_SERIALIZABLE ); @@ -138,7 +143,7 @@ public class LambdaFactory { invokeName, invokedType, samMethodType, - methodHandle, + LookupUtil.unreflect(executable), MethodTypeUtil.methodType(executable) ); } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/io/file/PathUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/io/file/PathUtilTest.java index 3e33f7c89..6aefc7dbc 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/io/file/PathUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/io/file/PathUtilTest.java @@ -1,5 +1,6 @@ package org.dromara.hutool.core.io.file; +import org.dromara.hutool.core.array.ArrayUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -69,7 +70,13 @@ public class PathUtilTest { @Test public void getMimeOfRarTest(){ final String contentType = FileUtil.getMimeType("a001.rar"); - Assertions.assertEquals("application/x-rar-compressed", contentType); + Assertions.assertTrue( + ArrayUtil.contains( + new String[]{ + "application/x-rar-compressed", + // JDK9+修改为此 + "application/vnd.rar"}, + contentType)); } @Test diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaUtilTest.java index b7ea25a06..daf27036e 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaUtilTest.java @@ -180,6 +180,17 @@ public class LambdaUtilTest { Assertions.assertTrue(bean.isFlag()); } + @Test + void buildSetterTest() { + final Bean bean = new Bean(); + bean.setId(2L); + bean.setFlag(false); + + final BiConsumer setter = LambdaUtil.buildSetter(Bean.class, "flag"); + setter.accept(bean, true); + Assertions.assertTrue(bean.isFlag()); + } + @SuppressWarnings("unchecked") @Test public void lambdaTest() {