反射获取类的泛型信息(解决泛型擦除问题)

在Java中,泛型信息在编译后会被擦除(Type Erasure),导致运行时无法直接获取泛型的具体类型。但通过反射机制,我们可以从类、字段或方法的签名中获取保留的泛型元数据。以下是关键方法:

1. 获取父类泛型参数

当子类继承泛型父类时,可通过getGenericSuperclass()获取具体类型:

// 定义泛型父类
public abstract class BaseDao<T> {
    private Class<T> entityClass;

    public BaseDao() {
        // 获取泛型T的实际类型
        Type type = getClass().getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType) type;
        this.entityClass = (Class<T>) pt.getActualTypeArguments()[0];
    }
}

// 子类继承时指定具体类型
public class UserDao extends BaseDao<User> {}

// 测试
UserDao dao = new UserDao();
System.out.println(dao.getEntityClass()); // 输出: class User

2. 获取字段泛型类型

通过Field.getGenericType()解析字段的泛型签名:

public class Container {
    private List<String> stringList;
}

// 获取字段泛型信息
Field field = Container.class.getDeclaredField("stringList");
Type genericType = field.getGenericType();

if (genericType instanceof ParameterizedType) {
    ParameterizedType pt = (ParameterizedType) genericType;
    Type actualType = pt.getActualTypeArguments()[0];
    System.out.println(actualType); // 输出: class java.lang.String
}

3. 获取方法返回类型泛型

使用Method.getGenericReturnType()解析方法返回值:

public interface DataService {
    List<Integer> getNumbers();
}

// 解析方法返回泛型
Method method = DataService.class.getMethod("getNumbers");
Type returnType = method.getGenericReturnType();

if (returnType instanceof ParameterizedType) {
    Type actualType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
    System.out.println(actualType); // 输出: class java.lang.Integer
}

4. 获取方法参数泛型

通过Method.getGenericParameterTypes()解析参数:

public class Processor {
    public void process(Map<String, Object> config) {}
}

// 解析参数泛型
Method method = Processor.class.getMethod("process", Map.class);
Type[] paramTypes = method.getGenericParameterTypes();

ParameterizedType mapType = (ParameterizedType) paramTypes[0];
Type[] mapArgs = mapType.getActualTypeArguments();
System.out.println(Arrays.toString(mapArgs)); 
// 输出: [class java.lang.String, class java.lang.Object]

关键点总结
场景 反射方法 返回类型
父类泛型参数 getClass().getGenericSuperclass() ParameterizedType
字段泛型类型 Field.getGenericType() Type
方法返回类型泛型 Method.getGenericReturnType() Type
方法参数泛型 Method.getGenericParameterTypes() Type[]

注意:泛型信息仅存在于显式声明的位置(如父类、字段、方法签名)。匿名内部类或未指定具体类型的变量无法获取泛型信息。

通过合理使用这些反射API,可在运行时突破泛型擦除限制,实现动态类型处理,适用于ORM框架、序列化工具等需要类型元数据的场景。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐