泛型类型擦除后,类型参数被系统性替换为最左边界类型:无界时替换为Object;单上界时替换为该上界;多上界时仅取第一个类或接口;擦除后编译器自动插入强制转换保障类型安全。

Java 中泛型类型擦除后,类型参数不是被“删除”,而是被**系统性地替换成某个具体类型**,这个替换目标取决于泛型声明时有没有上界(extends),以及上界的结构。核心规则就一条:**擦除目标是能作为实际类型的、最左的那个边界;若无界,则一律换成 Object。**
无界泛型 → 替换为 Object
当泛型参数没有 extends 限定(即 <t></t>)时,编译器统一用 Object 替代:
-
List<String>擦除后变成原始类型List,内部数组是Object[] -
Box<T>(无界)擦除后字段private T value变成private Object value -
<T> T getFirst(List<T> list)擦除为Object getFirst(List list)
单上界泛型 → 替换为该上界类型
有明确 extends X 的,直接替换成 X:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
-
<T extends Number>→ 擦除为Number(如NumberList<Integer>中的T value变成Number value) -
<T extends String>→ 擦除为String(虽不常见,但语法合法)
多上界泛型 → 只取第一个接口
多个边界用 & 连接时,仅第一个类或接口参与擦除,其余仅用于编译期校验:
立即学习“Java免费学习笔记(深入)”;
-
<T extends Comparable<T> & Serializable>→ 擦除为Comparable(因Comparable是第一个,且是接口;Serializable不参与擦除) -
<T extends Runnable & Cloneable & Comparable<T>>→ 仍擦除为Runnable
擦除后的真实表现
擦除不是简单删掉泛型符号,而是生成等效的非泛型代码,并由编译器自动插入强制转换来保障调用安全:
- 源码:
String s = pair.getFirst();(pair是Pair<String>) - 擦除后字节码实际执行:
String s = (String) pair.getFirst();(getFirst()返回Object) - 运行时 JVM 看不到任何泛型信息,所有
List<String>、List<Integer>都是同一个List类型

















