在 Java 反射(Reflection) 中,泛型的使用是一个“编译期有,运行期基本消失”的问题。下面我从 原理 → 常见用法 → 代码示例 → 注意事项 讲清楚。
Java 的泛型在运行时被擦除(Type Erasure)
所以:
Class 本身 拿不到泛型参数Type 体系 获取,而不是 ClassList<String> list = new ArrayList<>();
编译后等价于:
List list = new ArrayList();
所以在反射中:
Method m = obj.getClass().getMethod("getList");
Class<?> returnType = m.getReturnType(); // List,不是 List<String>
✅ 拿不到 <String>
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
}
}
✅ 这是反射 + 泛型最常用场景
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
}
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();
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 / 框架里最常用的技巧
| 类 / 接口 | 作用 |
|---|---|
Class |
运行期类型 |
Type |
所有类型的父接口 |
ParameterizedType |
泛型类型(如 List<String>) |
GenericArrayType |
泛型数组(如 T[]) |
TypeVariable |
泛型变量(如 T) |
WildcardType |
通配符(如 ? extends Number) |
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 大量使用这种方式
Class 获取泛型Class<?> c = List.class; // ❌ 拿不到 <String>
List<String> 和 List<Integer>List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
a.getClass() == b.getClass(); // true
反射不能直接获取泛型的“具体参数”,但可以通过字段、方法、父类定义中的
Type信息间接获取。
如果你愿意,我可以:
你更想深入哪一块?
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。