Java泛型仅存在于编译期,运行时通过类型擦除统一为原始类型;编译器自动插入类型转换、生成桥接方法,并在Signature属性中保留部分泛型信息,导致instanceof、new T()等操作不可行。

Java 泛型在运行时并不存在——它只是一种编译期机制,而“类型擦除”正是揭示这一真相的钥匙。理解它,就等于看清了泛型在 JVM 底层的真实模样:不是参数化的类型,而是被规整为原始类型的普通类、方法和字段。
泛型代码在字节码里长什么样
你写的 List<string></string> 或 Box<integer></integer>,编译后在 .class 文件中根本找不到任何 <string></string> 或 <integer></integer> 字样。JVM 看到的只有:
-
List(不是List<string></string>) -
Box(不是Box<integer></integer>) - 所有泛型参数都被替换成其边界类型:无界
T→Object;T extends Number→Number;T extends Comparable & Serializable→Comparable(取第一个上界)
编译器悄悄做了什么补偿
擦除不是简单删掉泛型符号,而是一套有逻辑的重写过程:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 自动插入强制类型转换:比如
list.get(0)返回Object,但编译器会在调用处加(String)转换,确保语义不变 - 生成桥接方法(Bridge Method):当子类重写泛型父类方法时(如
ArrayList<string></string>重写AbstractList<string>.set(int, String)</string>),编译器会额外生成一个签名匹配原始父类的方法(如set(int, Object)),供 JVM 动态分派使用 - 保留泛型签名在
Signature属性中:虽然运行时不能直接读getGenericSuperclass()得到泛型实参,但通过反射访问字节码中的Signature属性,仍可还原部分泛型结构(如继承关系中的泛型声明)
为什么 instanceof、new T()、static 泛型字段都不可行
这些限制不是语法疏漏,而是类型擦除的必然结果:
立即学习“Java免费学习笔记(深入)”;
-
obj instanceof List<string></string>编译失败:因为运行时没有List<string></string>这个类型,只有List,JVM 无法区分不同泛型实例 -
new T()不允许:擦除后T已变成Object或某个上界类,但编译器无法确定具体构造器,且可能抽象(如T extends Number) - 静态上下文中不能引用
T:静态变量/方法属于类本身,而泛型类型参数属于实例化后的类型,擦除后T已无独立存在依据
面向对象视角下的真实映射关系
从 OOP 的本质看,泛型类不是多个类型,而是一个模板生成的「同一类」:
-
ArrayList<string></string>和ArrayList<integer></integer>在运行时是同一个类ArrayList,共享同一份字节码、同一套方法表、同一个 Class 对象 - 它们之间的差异仅存在于编译期检查和插入的转型逻辑中,而非 JVM 类加载或对象模型层面
- 这也解释了为何泛型不能用于方法重载:两个方法签名
foo(List<string>)</string>和foo(List<integer>)</integer>擦除后都是foo(List),编译器直接报错

















