ParameterizedType
好的,我来用最通俗易懂的方式解释 ParameterizedType。
一句话理解
ParameterizedType 就是 Java 的"后悔药",能找回被"类型擦除"弄丢的泛型信息。
一个超简单的例子:水果篮子
想象你有几个篮子:
// 普通篮子 - 什么都能放,但很混乱
Basket basket1 = new Basket(); // 可能放水果,也可能放石头// 泛型篮子 - 标明用途的篮子
Basket<String> fruitBasket = new Basket<>(); // 专门放水果的篮子
Basket<Integer> numberBasket = new Basket<>(); // 专门放数字的篮子
问题来了:“类型擦除”
Java 为了兼容老版本,在程序运行时会把泛型信息擦除:
- 编译时:编译器知道
fruitBasket是放水果的,numberBasket是放数字的 - 运行时:JVM 看到的都是普通的
Basket,分不清哪个是放什么的
这就好比:
- 写标签时:你在篮子上贴了"水果专用"、“数字专用”
- 实际用时:有人把标签都撕了,所有篮子看起来一模一样
ParameterizedType 的作用
ParameterizedType 就是那个能帮你找回被撕掉标签的工具!
什么时候标签没被完全撕掉?
在类的成员变量声明处,泛型信息会被保留:
public class MyClass {// 这里的泛型信息会被保留!ParameterizedType 就能看到private List<String> names; // 我知道这是放String的List!private Map<String, Integer> scores; // 我知道这是String->Integer的Map!
}
实际代码演示
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;public class MyClass {// 这些字段的泛型信息会被保留private List<String> names;private Map<String, Integer> scores;private List<List<String>> nestedList; // 甚至嵌套的泛型也能看到!public static void main(String[] args) throws Exception {// 查看 names 字段的泛型信息Field namesField = MyClass.class.getDeclaredField("names");// 普通看法:只能看到是个List,不知道里面放什么System.out.println("普通看法: " + namesField.getType()); // 输出: interface java.util.List (只知道是篮子,不知道放什么)// 用ParameterizedType看:能看到详细信息!Type genericType = namesField.getGenericType();System.out.println("详细看法: " + genericType);// 输出: java.util.List<java.lang.String> (知道是放String的篮子!)if (genericType instanceof ParameterizedType) {ParameterizedType pType = (ParameterizedType) genericType;// 1. 问:篮子本身是什么?System.out.println("篮子类型: " + pType.getRawType()); // 输出: interface java.util.List// 2. 问:篮子里规定放什么?Type[] typeArgs = pType.getActualTypeArguments();System.out.println("规定内容: " + typeArgs[0]); // 输出: class java.lang.String}System.out.println("---");// 查看嵌套泛型 nestedListField nestedField = MyClass.class.getDeclaredField("nestedList");Type nestedType = nestedField.getGenericType();System.out.println("嵌套泛型: " + nestedType);// 输出: java.util.List<java.util.List<java.lang.String>>}
}
运行结果:
普通看法: interface java.util.List
详细看法: java.util.List<java.lang.String>
篮子类型: interface java.util.List
规定内容: class java.lang.String
---
嵌套泛型: java.util.List<java.util.List<java.lang.String>>
实际应用场景
场景1:JSON解析(最常用)
// 没有ParameterizedType:
String json = "[\"苹果\", \"香蕉\"]";
List list = gson.fromJson(json, List.class);
// Gson懵逼:我知道这是个List,但里面该转成String?Integer?User对象?// 有ParameterizedType:
Type listType = new TypeToken<List<String>>(){}.getType();
List<String> fruits = gson.fromJson(json, listType);
// Gson开心:哦!原来是转成String的List,我知道了!
场景2:数据转换
框架需要知道你的 List 里到底要装什么类型的对象,才能正确创建实例、转换数据。
核心方法总结
ParameterizedType 主要有三个方法:
-
getRawType()- 问:“篮子本身是什么?”- 回答:
List.class、Map.class等
- 回答:
-
getActualTypeArguments()- 问:“篮子里规定放什么?”- 回答:
[String.class]、[String.class, Integer.class]等
- 回答:
-
getOwnerType()- 问:“这个篮子属于哪个大篮子?”(用得较少)

总结
| 概念 | 通俗解释 | 例子 |
|---|---|---|
| 泛型 | 给篮子贴标签,规定放什么 | List<String> |
| 类型擦除 | 运行时标签被撕掉 | 所有 List 看起来都一样 |
| ParameterizedType | 找回被撕标签的工具 | 能发现 names 字段是 List<String> |
| 为什么重要 | 没有它,框架不知道你的容器里要装什么 | JSON解析、依赖注入等都依赖它 |
简单记:ParameterizedType = 泛型信息的"时光机",能回到编译时看看当初的类型约定!
