如何从泛型类中获取类型变量与字段的映射关系?
获取泛型类字段与类型变量的映射关系
要解决泛型擦除导致无法直接获取字段关联类型变量的问题,核心是利用Java反射API读取字段的泛型类型签名,而非擦除后的原始类型。以下是具体实现方式,同时结合Jackson反序列化泛型的原理说明:
1. 直接获取字段与类型变量的映射
不要使用Field.getType()(返回擦除后的类型),改用Field.getGenericType()保留编译时的泛型信息,直接提取字段关联的类型变量:
import java.lang.reflect.Field; import java.lang.reflect.TypeVariable; import java.util.HashMap; import java.util.Map; class RowClass<T1, T2> { public T1 t1; public T2 t2; public T1 t3; } public class GenericFieldMapping { public static void main(String[] args) { Map<String, String> fieldTypeVarMap = new HashMap<>(); for (Field field : RowClass.class.getDeclaredFields()) { Type<?> genericType = field.getGenericType(); if (genericType instanceof TypeVariable) { TypeVariable<?> typeVar = (TypeVariable<?>) genericType; fieldTypeVarMap.put(field.getName(), typeVar.getName()); } } // 输出映射关系 fieldTypeVarMap.forEach((field, typeVar) -> System.out.println(field + " -> " + typeVar)); } }
运行结果:
t1 -> T1 t2 -> T2 t3 -> T1
2. 结合子类实际类型参数,获取字段的实际类型
如果有子类指定了泛型的实际类型(比如你定义的RowClassImpl),可以先建立类型变量与实际类型的映射,再关联到对应字段:
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.HashMap; import java.util.Map; class RowClass<T1, T2> { public T1 t1; public T2 t2; public T1 t3; } class RowClassImpl extends RowClass<String, Integer> {} public class GenericFieldActualType { public static void main(String[] args) { // 1. 建立类型变量与实际类型的映射 ParameterizedType superType = (ParameterizedType) RowClassImpl.class.getGenericSuperclass(); Type[] actualTypes = superType.getActualTypeArguments(); TypeVariable<?>[] typeVars = RowClass.class.getTypeParameters(); Map<TypeVariable<?>, Type> typeVarToActualType = new HashMap<>(); for (int i = 0; i < typeVars.length; i++) { typeVarToActualType.put(typeVars[i], actualTypes[i]); } // 2. 遍历字段,获取实际类型 for (Field field : RowClass.class.getDeclaredFields()) { Type genericType = field.getGenericType(); if (genericType instanceof TypeVariable) { Type actualType = typeVarToActualType.get(genericType); System.out.println(field.getName() + " -> " + actualType.getTypeName()); } } } }
运行结果:
t1 -> java.lang.String t2 -> java.lang.Integer t3 -> java.lang.String
3. Jackson反序列化泛型的核心原理
Jackson处理List<String>这类泛型时,逻辑和上述实现一致:
- 当你使用
new TypeReference<List<String>>() {}时,Jackson通过反射读取这个匿名内部类的父类(TypeReference)的参数化类型,拿到完整的泛型信息。 - 内部会构建类型变量到实际类型的映射表,反序列化时根据该映射解析JSON数据,避免泛型擦除导致的类型丢失。
内容的提问来源于stack exchange,提问作者Machi
相关产品推荐
相关产品推荐

