Java 泛型快速学习指南(面向接口扫描场景)
目标:让你能读懂 / 看懂被扫描 Java 代码里的泛型,理解扫描工具在「DTO 展开、包装类解包」时到底在干什么。
不需要背语法细节,重点是建立直观理解。
摘要 :本文用最短篇幅讲清 Java 泛型的核心概念------泛型是给容器/方法提前声明的占位类型,编译期定死类型、免强转。内容覆盖泛型类、泛型方法、多类型参数、泛型嵌套(Result<List<OrderDTO>>这类"套娃")、通配符?、数组/List 两行式输出口径,以及泛型擦除为何导致运行时拿不到T。文末附最小速查表,面向接口扫描场景,帮你建立直观理解、读懂被扫描代码里的泛型。
一、泛型是什么(一句话)
泛型 = 给"容器/方法"提前声明一个"占位类型 T",使用时再填上具体类型。
没有泛型时,集合里放的是 Object,取出来要强转,容易出错:
java
List list = new ArrayList();
list.add("abc");
String s = (String) list.get(0); // 必须强转,类型不安全
有了泛型,类型在编译期就定死,取出来直接用:
java
List<String> list = new ArrayList<>();
list.add("abc");
String s = list.get(0); // 不需要强转,编译器保证里面一定是 String
核心好处:编译期类型检查 + 免强转。
二、最基本的几种写法
1. 类上的泛型(泛型类)
java
class Box<T> { // T 是类型占位符,名字随便起(常用 T/E/K/V)
private T value;
public T getValue() { return value; }
public void setValue(T value) { this.value = value; }
}
// 使用时:
Box<String> b = new Box<>();
b.setValue("你好"); // 这里 T 被"填"成了 String
2. 方法上的泛型(泛型方法)
java
public <T> T getFirst(List<T> list) {
return list.get(0);
}
// 调用时 T 由实参自动推断
String s = getFirst(Arrays.asList("a", "b"));
3. 多个类型参数
java
class Pair<K, V> {
private K key;
private V value;
}
// 你项目里常见:Map<String, OrderDTO> 就是 K=String, V=OrderDTO
三、你最可能遇到的"套娃"类型
1. 泛型嵌套(重点)
java
List<OrderDTO> // 元素类型是 OrderDTO
Result<List<OrderDTO>> // Result 包裹 List,List 包裹 OrderDTO
Page<OrderVO> // 分页对象,里面是 OrderVO 列表
理解口诀:从外往里一层层剥。扫描工具也正是这么做的:
- 看到
Result<T>→ 先把Result这个"容器"当一行; - 再把
T(实参)树挂到它下面继续展开。
2. 通配符 ?(你大概只需知道它存在)
java
List<?> // 任意类型的 List
List<? extends Number> // 元素类型是 Number 或其子类(上界)
List<? super Integer> // 元素类型是 Integer 或其父类(下界)
实际扫描里一般不用深究,工具多半按"保留容器行 + 不强行展开"处理。
3. 数组 / List 两行式(对应你工具的输出口径)
源码:
java
private List<OrderItemDTO> items;
输出报文里会变成两行:
- 数组行:
itemstype=List<OrderItemDTO> - 元素行:挂在
items下,name=OrderItemDTO,继续展开其字段
四、泛型擦除(为什么运行时拿不到 T)
Java 的泛型是编译期 的:编译完之后,List<String> 和 List<Integer> 在 JVM 里都是同一个 List(类型信息被"擦掉")。
java
// 编译后等价于:
List list = new ArrayList();
这解释了:
- 为什么不能
new T()、不能new List<T>()(运行时不知道 T 是谁); - 为什么扫描工具必须靠读源码/字节码里的声明来还原泛型,而不能在运行时探测。
五、最小速查表
| 写法 | 读法 |
|---|---|
T / E / K / V |
类型占位符(Type/Element/Key/Value) |
List<String> |
装 String 的列表 |
Map<String, OrderDTO> |
key=String, value=OrderDTO 的映射 |
Result<T> |
泛型包装容器,T 是真正的业务数据 |
Result<List<X>> |
包装容器里套了一个 X 列表 |
? extends X |
X 或其子类 |
? super X |
X 或其父类 |
想深入再补:泛型边界
<T extends Comparable<T>>、泛型构造器、桥接方法。日常接口扫描用不到,遇到再说。