java泛型在字节码中被擦除,统一替换为原始类型或上界,并插入checkcast指令保障类型安全;signature属性保留泛型元数据供反射使用;桥接方法解决因擦除导致的多态失效问题。

Java 泛型擦除机制在字节码层面不保留泛型类型参数,而是统一替换为原始类型(raw type)或其上界,并辅以自动插入的类型转换指令来维持编译期类型安全。
字节码中泛型信息被彻底移除
泛型仅存在于源码和编译过程,javac 编译后,所有 T、List<string></string>、Map<k v></k> 等泛型声明全部消失。字节码里只出现原始类型,例如:
-
List<string></string>→ 字节码中为List -
Box<integer></integer>→ 字节码中为Box,字段和方法签名里的T全部变成Object(无界时)或Number(如<t extends number></t>) - 通过
javap -c Box.class查看,你会发现所有方法参数、返回值、局部变量都使用Object,没有泛型痕迹
强制类型转换由编译器自动插入
为弥补运行时类型信息缺失,编译器在调用泛型方法后,自动添加 checkcast 指令,确保取值时类型正确:
- 比如
String s = box.get();(其中box是Box<string></string>) - 编译后等价于:
Object tmp = box.get(); String s = (String) tmp; - 对应字节码会包含
checkcast java/lang/String指令,失败则抛ClassCastException
Signature 属性保留元数据供反射使用
虽然 Code 区域擦除了泛型,但 class 文件的属性表中新增了 Signature 字段,用于存储泛型签名:
- 类定义
class IntList extends ArrayList<integer></integer>→Signature属性记录Ljava/util/ArrayList<ljava>;</ljava> - 方法
<t> T getValue()</t>的返回类型签名也会存入Signature - 这使得
getGenericSuperclass()、getGenericReturnType()等反射 API 能还原泛型信息,但仅限于类声明、方法签名、父类继承链等**静态可推导位置**,不适用于局部变量或运行时对象
桥接方法确保多态性不被破坏
当泛型类继承或实现带类型参数的接口时,编译器会生成桥接方法(bridge method),避免因擦除导致重写失效:
- 例如
class StringBox extends Box<string></string>重写了get(),返回String - 但父类擦除后
Box.get()返回Object,JVM 方法签名不匹配 - 编译器自动添加一个
public Object get()桥接方法,内部调用String get()并返回转型结果 - 该桥接方法在字节码中可见,标记为
ACC_BRIDGE | ACC_SYNTHETIC
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











