From e9aa7b327927491770c1d4610350c7cd6a1ae9d9 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 30 Jun 2023 18:17:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DTypeUtil.getTypeArgument?= =?UTF-8?q?=E5=AF=B9=E5=AE=9E=E7=8E=B0=E6=8E=A5=E5=8F=A3=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=B8=8D=E5=85=A8=E9=9D=A2=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/hutool/core/reflect/TypeUtil.java | 74 +++++++++++++++---- .../hutool/core/reflect/IssueI7CRIWTest.java | 60 +++++++++++++++ 2 files changed, 121 insertions(+), 13 deletions(-) create mode 100755 hutool-core/src/test/java/org/dromara/hutool/core/reflect/IssueI7CRIWTest.java diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/TypeUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/TypeUtil.java index 86ec1b7d5..768065df8 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/TypeUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/TypeUtil.java @@ -13,6 +13,7 @@ package org.dromara.hutool.core.reflect; import org.dromara.hutool.core.array.ArrayUtil; +import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.util.ObjUtil; import java.lang.reflect.Field; @@ -21,6 +22,7 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; +import java.util.List; import java.util.Map; /** @@ -276,23 +278,69 @@ public class TypeUtil { * @since 4.5.2 */ public static ParameterizedType toParameterizedType(final Type type) { - ParameterizedType result = null; + return toParameterizedType(type, 0); + } + + /** + * 将{@link Type} 转换为{@link ParameterizedType}
+ * {@link ParameterizedType}用于获取当前类或父类中泛型参数化后的类型
+ * 一般用于获取泛型参数具体的参数类型,例如: + * + *
{@code
+	 *   class A
+	 *   class B extends A;
+	 * }
+ *

+ * 通过此方法,传入B.class即可得到B对应的{@link ParameterizedType},从而获取到String + * + * @param type {@link Type} + * @param interfaceIndex 实现的第几个接口 + * @return {@link ParameterizedType} + * @since 4.5.2 + */ + public static ParameterizedType toParameterizedType(final Type type, final int interfaceIndex) { if (type instanceof ParameterizedType) { - result = (ParameterizedType) type; - } else if (type instanceof Class) { - final Class clazz = (Class) type; - Type genericSuper = clazz.getGenericSuperclass(); - if (null == genericSuper || Object.class.equals(genericSuper)) { - // 如果类没有父类,而是实现一些定义好的泛型接口,则取接口的Type - final Type[] genericInterfaces = clazz.getGenericInterfaces(); - if (ArrayUtil.isNotEmpty(genericInterfaces)) { - // 默认取第一个实现接口的泛型Type - genericSuper = genericInterfaces[0]; + return (ParameterizedType) type; + } + + if (type instanceof Class) { + final ParameterizedType[] generics = getGenerics((Class) type); + if(generics.length > interfaceIndex){ + return generics[interfaceIndex]; + } + } + + return null; + } + + /** + * 获取指定类所有泛型父类和泛型接口 + * + * @param clazz 类 + * @return 泛型父类或接口数组 + * @since 6.0.0 + */ + public static ParameterizedType[] getGenerics(final Class clazz) { + final List result = ListUtil.of(false); + // 泛型父类(父类及祖类优先级高) + final Type genericSuper = clazz.getGenericSuperclass(); + if(null != genericSuper && !Object.class.equals(genericSuper)){ + final ParameterizedType parameterizedType = toParameterizedType(genericSuper); + if(null != parameterizedType){ + result.add(parameterizedType); + } + } + + // 泛型接口 + final Type[] genericInterfaces = clazz.getGenericInterfaces(); + if (ArrayUtil.isNotEmpty(genericInterfaces)) { + for (final Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType) { + result.add((ParameterizedType) genericInterface); } } - result = toParameterizedType(genericSuper); } - return result; + return result.toArray(new ParameterizedType[0]); } /** diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/reflect/IssueI7CRIWTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/reflect/IssueI7CRIWTest.java new file mode 100755 index 000000000..313b710da --- /dev/null +++ b/hutool-core/src/test/java/org/dromara/hutool/core/reflect/IssueI7CRIWTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.reflect; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Type; + +public class IssueI7CRIWTest { + + @Test + void getTypeArgumentsTest() { + // 无法从继承获取泛型,则从接口获取 + Type type = TypeUtil.getTypeArgument(C.class); + Assertions.assertEquals(type, String.class); + + // 继承和第一个接口都非泛型接口,则从找到的第一个泛型接口获取 + type = TypeUtil.getTypeArgument(D.class); + Assertions.assertEquals(type, String.class); + } + + static class A{ + + } + + static class AT{ + + } + + interface Face1{ + + } + + interface Face2{ + + } + + static class B extends A{ + + } + + static class C extends A implements Face1{ + + } + + static class D extends A implements Face2, Face1{ + + } +}