From 6bccf5907986cce4e366b8c2fb91469c7d28ad96 Mon Sep 17 00:00:00 2001 From: achao Date: Thu, 18 Aug 2022 15:54:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DLambdaUtil=E5=AF=B9=E5=A4=9A?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E4=B8=94=E5=8F=82=E6=95=B0=E4=B8=BA=E5=8C=85?= =?UTF-8?q?=E5=90=AB=E6=95=B0=E7=BB=84=E7=9A=84lambda=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81;=E4=BC=98=E5=8C=96clazz=E8=8E=B7=E5=8F=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E7=9B=B4=E6=8E=A5=E4=BB=8Eexecutable?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=80=8C=E4=B8=8D=E6=98=AF=E5=8F=8D=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/lang/func/LambdaInfo.java | 36 +++++++++++-------- .../hutool/core/lang/func/LambdaUtilTest.java | 12 ++++--- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java index a9563e9cf..da5fdcbad 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java @@ -1,7 +1,7 @@ package cn.hutool.core.lang.func; import cn.hutool.core.classloader.ClassLoaderUtil; -import cn.hutool.core.reflect.FieldUtil; +import cn.hutool.core.text.StrPool; import java.lang.invoke.SerializedLambda; import java.lang.reflect.Constructor; @@ -30,34 +30,42 @@ public class LambdaInfo { this.parameterTypes = method.getGenericParameterTypes(); this.returnType = method.getGenericReturnType(); this.name = method.getName(); + this.clazz = method.getDeclaringClass(); } else if (executable instanceof Constructor) { final Constructor constructor = (Constructor) executable; this.parameterTypes = constructor.getGenericParameterTypes(); this.returnType = constructor.getDeclaringClass(); this.name = constructor.getName(); + this.clazz = constructor.getDeclaringClass(); } else { throw new IllegalArgumentException("Unsupported executable type: " + executable.getClass()); } final int index = lambda.getInstantiatedMethodType().indexOf(";)"); if (index > -1) { - final boolean isArray = lambda.getInstantiatedMethodType().startsWith("(["); - if (isArray) { - try { - this.instantiatedTypes = new Type[]{Class.forName(lambda.getInstantiatedMethodType().replace("/", ".").substring(0, index).substring(1) + ";")}; - } catch (final ClassNotFoundException e) { - throw new IllegalStateException(e); - } - } else { - final String[] instantiatedTypeNames = lambda.getInstantiatedMethodType().substring(2, index).split(";L"); - this.instantiatedTypes = new Type[instantiatedTypeNames.length]; - for (int i = 0; i < instantiatedTypeNames.length; i++) { - this.instantiatedTypes[i] = ClassLoaderUtil.loadClass(instantiatedTypeNames[i]); + final String className = lambda.getInstantiatedMethodType().substring(1, index + 1); + final String[] instantiatedTypeNames = className.split(";"); + final Type[] types = new Type[instantiatedTypeNames.length]; + for (int i = 0; i < instantiatedTypeNames.length; i++) { + final boolean isArray = instantiatedTypeNames[i].startsWith(StrPool.BRACKET_START); + if (isArray && !instantiatedTypeNames[i].endsWith(";")) { + // 如果是数组,需要以 ";" 结尾才能加载 + instantiatedTypeNames[i] += ";"; + } else { + if (instantiatedTypeNames[i].startsWith("L")) { + // 如果以 "L" 开头,删除 L + instantiatedTypeNames[i] = instantiatedTypeNames[i].substring(1); + } + if (instantiatedTypeNames[i].endsWith(";")) { + // 如果以 ";" 结尾,删除 ";" + instantiatedTypeNames[i] = instantiatedTypeNames[i].substring(0, instantiatedTypeNames[i].length() - 1); + } } + types[i] = ClassLoaderUtil.loadClass(instantiatedTypeNames[i]); } + this.instantiatedTypes = types; } else { this.instantiatedTypes = new Type[0]; } - this.clazz = (Class) FieldUtil.getFieldValue(executable, "clazz"); this.executable = executable; this.lambda = lambda; } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java index e923a604a..e0ddc9428 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java @@ -7,11 +7,9 @@ import org.junit.Assert; import org.junit.Test; import java.io.Serializable; -import java.lang.reflect.Array; import java.util.Objects; import java.util.stream.Stream; -@SuppressWarnings("unchecked") public class LambdaUtilTest { @Test @@ -29,7 +27,7 @@ public class LambdaUtilTest { } @Test - public void resolveTest() { + public void resolveTest() { Stream.of(() -> { // 引用构造函数 final Func0 lambda = MyTeacher::new; @@ -41,7 +39,7 @@ public class LambdaUtilTest { final Func1 lambda = MyTeacher[]::new; final LambdaInfo lambdaInfo = LambdaUtil.resolve(lambda); Assert.assertEquals(int.class, lambdaInfo.getParameterTypes()[0]); - Assert.assertEquals(MyTeacher.class, ((Class) lambdaInfo.getReturnType()).getComponentType()); + Assert.assertEquals(MyTeacher[].class, lambdaInfo.getReturnType()); }, () -> { // 引用静态方法 final Func0 lambda = MyTeacher::takeAge; @@ -80,6 +78,12 @@ public class LambdaUtilTest { Assert.assertEquals(String.class, lambdaInfo.getParameterTypes()[4]); Assert.assertEquals(void.class, lambdaInfo.getReturnType()); + }, () -> { + // 一些特殊的lambda + Assert.assertEquals("T[]", LambdaUtil.>>resolve(Stream::of).getParameterTypes()[0].getTypeName()); + Assert.assertEquals(MyTeacher[][].class, LambdaUtil.>resolve(MyTeacher[][]::new).getReturnType()); + Assert.assertEquals(Integer[][][].class, LambdaUtil.>resolve(a -> {}).getParameterTypes()[0]); + Assert.assertEquals(Integer[][][].class, LambdaUtil.resolve((Serializable & Consumer3) (a, b, c) -> {}).getParameterTypes()[0]); }).forEach(Runnable::run); }