如何在Java中解析实现类相对于泛型类/接口的所有实际类型?
解析泛型父类/接口的实际类型参数(忽略类型名称)
问题描述
我正尝试解析实现类相对于泛型类或接口的所有实际类型。已编写了ActualTypeArgumentsResolver来实现此功能,但它仅在类型名称保持一致时生效。希望忽略TypeName并获取所有实际类型,该如何实现?
测试用例
@Test public void testIndirectlyExtendedGenericSuperclassWithDiffTypeName() { abstract class AbstractClass3<AAA, BBB, CCC> { } abstract class AbstractClass2<AA, BB, CC> extends AbstractClass3<CC, Map, BB> { } abstract class AbstractClass1<A, B> extends AbstractClass2<Long, A, Boolean> { } class Impl extends AbstractClass1<String, Integer> {} Type[] arr = ActualTypeArgumentsResolver.resolve(Impl.class, AbstractClass3.class); Assert.assertTrue(arr.length == 3); Assert.assertEquals(arr[0], Boolean.class); Assert.assertEquals(arr[1], Map.class); Assert.assertEquals(arr[2], String.class); }
解决方案
要实现忽略类型名称、正确解析跨多层继承的泛型实际类型参数,核心是跟踪类型参数的映射关系,而非依赖类型参数名称匹配。以下是具体实现思路和代码:
核心思路
- 从目标实现类开始,向上遍历继承链,直到定位到目标泛型类/接口。
- 每一层继承中,记录当前类泛型参数与父类泛型参数的映射关系(比如
AbstractClass2的CC对应AbstractClass3的AAA)。 - 逐层替换映射关系,最终将目标类的原始类型参数替换为实现类传递的实际类型。
实现代码
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.HashMap; import java.util.Map; public class ActualTypeArgumentsResolver { public static Type[] resolve(Class<?> implClass, Class<?> targetGenericClass) { // 存储类型参数映射:父类参数 -> 子类传递的实际类型/参数 Map<TypeVariable<?>, Type> typeMap = new HashMap<>(); Type currentType = implClass; while (currentType != null) { if (currentType instanceof Class) { // 普通类直接取父类 currentType = ((Class<?>) currentType).getGenericSuperclass(); continue; } ParameterizedType parameterizedType = (ParameterizedType) currentType; Class<?> rawType = (Class<?>) parameterizedType.getRawType(); // 找到目标泛型类,解析最终实际类型 if (rawType == targetGenericClass) { Type[] actualTypeArgs = parameterizedType.getActualTypeArguments(); Type[] result = new Type[actualTypeArgs.length]; for (int i = 0; i < actualTypeArgs.length; i++) { result[i] = resolveType(actualTypeArgs[i], typeMap); } return result; } // 记录当前层类型参数映射 TypeVariable<?>[] typeParams = rawType.getTypeParameters(); Type[] actualArgs = parameterizedType.getActualTypeArguments(); for (int i = 0; i < typeParams.length; i++) { Type resolvedType = resolveType(actualArgs[i], typeMap); typeMap.put(typeParams[i], resolvedType); } // 继续向上遍历父类 currentType = rawType.getGenericSuperclass(); } throw new IllegalArgumentException(targetGenericClass.getName() + " is not a superclass of " + implClass.getName()); } private static Type resolveType(Type type, Map<TypeVariable<?>, Type> typeMap) { if (type instanceof TypeVariable<?>) { TypeVariable<?> var = (TypeVariable<?>) type; // 递归解析直到找到实际类型 Type resolved = typeMap.get(var); return resolved != null ? resolveType(resolved, typeMap) : var; } // 处理嵌套参数化类型(如Map<K,V>) if (type instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) type; Type[] args = paramType.getActualTypeArguments(); Type[] resolvedArgs = new Type[args.length]; for (int i = 0; i < args.length; i++) { resolvedArgs[i] = resolveType(args[i], typeMap); } return new ParameterizedType() { @Override public Type[] getActualTypeArguments() { return resolvedArgs; } @Override public Type getRawType() { return paramType.getRawType(); } @Override public Type getOwnerType() { return paramType.getOwnerType(); } }; } // 普通类或基本类型直接返回 return type; } }
代码说明
resolve方法:遍历继承链,逐层建立类型参数映射,找到目标泛型类后解析最终实际类型。resolveType方法:递归解析类型参数,替换映射中的参数为实际类型,支持嵌套参数化类型的解析。- 实现不依赖类型参数名称(如
AAA、AA、A这类名称不影响解析),仅关注参数位置和映射关系。
验证结果
运行提供的测试用例,所有断言均会通过:
arr[0]对应AbstractClass3的AAA,经多层映射后为Boolean.classarr[1]对应BBB,直接为Map.classarr[2]对应CCC,映射后为String.class
内容的提问来源于stack exchange,提问作者Universe Whole-Xuan
相关产品推荐
相关产品推荐

