温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

泛型在反射中怎么用

发布时间:2026-07-15 12:26:13 来源:亿速云 阅读:90 作者:小樊 栏目:编程语言

Java 反射(Reflection) 中,泛型的使用是一个“编译期有,运行期基本消失”的问题。下面我从 原理 → 常见用法 → 代码示例 → 注意事项 讲清楚。


一、先说结论(很重要)

Java 的泛型在运行时被擦除(Type Erasure)
所以:

  • Class 本身 拿不到泛型参数
  • 字段 / 方法参数 / 方法返回值 / 父类定义 可以保留泛型信息
  • 这些信息通过 Type 体系 获取,而不是 Class

二、泛型擦除在反射中的体现

List<String> list = new ArrayList<>();

编译后等价于:

List list = new ArrayList();

所以在反射中:

Method m = obj.getClass().getMethod("getList");
Class<?> returnType = m.getReturnType(); // List,不是 List<String>

拿不到 <String>


三、反射中能获取泛型的地方(重点)

✅ 1. 获取 字段的泛型类型

class User {
    private List<String> roles;
}
Field field = User.class.getDeclaredField("roles");

Type type = field.getGenericType();

if (type instanceof ParameterizedType pType) {
    Type[] actualTypes = pType.getActualTypeArguments();
    for (Type t : actualTypes) {
        System.out.println(t); // class java.lang.String
    }
}

这是反射 + 泛型最常用场景


✅ 2. 获取 方法返回值的泛型

class Service {
    public Map<String, Integer> getData() {
        return null;
    }
}
Method method = Service.class.getMethod("getData");
Type returnType = method.getGenericReturnType();

if (returnType instanceof ParameterizedType pType) {
    Type[] types = pType.getActualTypeArguments();
    System.out.println(types[0]); // String
    System.out.println(types[1]); // Integer
}

✅ 3. 获取 方法参数的泛型

class Service {
    public void setData(Map<String, Integer> map) {}
}
Method method = Service.class.getMethod("setData", Map.class);
Type[] paramTypes = method.getGenericParameterTypes();

ParameterizedType pType = (ParameterizedType) paramTypes[0];
Type[] actualTypes = pType.getActualTypeArguments();

✅ 4. 获取 父类的泛型(非常常见)

class BaseDao<T> {}

class UserDao extends BaseDao<String> {}
Type superClass = UserDao.class.getGenericSuperclass();

if (superClass instanceof ParameterizedType pType) {
    Type[] types = pType.getActualTypeArguments();
    System.out.println(types[0]); // class java.lang.String
}

这是 ORM / 框架里最常用的技巧


四、反射中泛型相关的核心 API

类 / 接口 作用
Class 运行期类型
Type 所有类型的父接口
ParameterizedType 泛型类型(如 List<String>
GenericArrayType 泛型数组(如 T[]
TypeVariable 泛型变量(如 T
WildcardType 通配符(如 ? extends Number

五、一个完整示例(通用 DAO)

class BaseDao<T> {
    private Class<T> entityClass;

    public BaseDao() {
        Type superClass = getClass().getGenericSuperclass();
        ParameterizedType pType = (ParameterizedType) superClass;
        entityClass = (Class<T>) pType.getActualTypeArguments()[0];
    }

    public void save(T entity) {
        System.out.println("保存:" + entityClass.getName());
    }
}

class User {}

class UserDao extends BaseDao<User> {}
new UserDao().save(new User());

✅ 框架中 Hibernate / MyBatis / Spring 大量使用这种方式


六、常见误区(⚠️)

❌ 1. 直接通过 Class 获取泛型

Class<?> c = List.class; // ❌ 拿不到 <String>

❌ 2. 认为运行时还能区分 List<String>List<Integer>

List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();

a.getClass() == b.getClass(); // true

七、一句话总结

反射不能直接获取泛型的“具体参数”,但可以通过字段、方法、父类定义中的 Type 信息间接获取。

如果你愿意,我可以:

  • Spring / MyBatis 的真实源码 给你讲
  • 或结合 Kotlin / Android 场景讲
  • 或讲 为什么 Java 要泛型擦除

你更想深入哪一块?

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI