Java泛型类型擦除是编译阶段行为:无界泛型替为Object,有界泛型取最左上界,生成桥接方法保障多态,运行时无法获取真实类型参数。

Java泛型的类型擦除不是运行时行为,而是编译器在编译阶段完成的“翻译动作”:所有泛型参数被系统性地替换成具体类型,同时移除字节码中的泛型标识。这个替换过程严格遵循边界规则,核心目标是保证向后兼容(适配 Java 5 之前的 JVM),同时由编译器插入隐式转换来维持类型安全。
无界泛型一律转为 Object
当泛型声明中没有 extends 限定(即无上界)时,编译器统一用 Object 替代该类型参数:
-
List<String>→ 擦除为原始类型List,内部数组为Object[] -
Box<T>(未限定)→ 擦除为Box,字段private T value变成private Object value -
<T> T getFirst(List<T> list)→ 擦除为Object getFirst(List list)
有界泛型按规则取第一个上界
若泛型指定了上界,编译器会用其最左的、可作为实际类型的那个边界来替换:
-
<T extends Number>→ 替换为Number(如NumberList<Integer>擦除后字段类型为Number) -
<T extends Comparable<T> & Serializable>→ 替换为Comparable(因 Java 接口继承限制,仅取首个接口) -
<T extends String>→ 替换为String(虽不常用,但语法合法,擦除后直接使用String)
方法签名与桥接方法同步调整
泛型方法擦除不仅改参数类型,还会生成桥接方法以支撑多态调用:
- 子类重写
<T> void process(T item),擦除后变成void process(Object item) - 若父类是泛型类
Processor<String>,子类StringProcessor重写该方法,编译器自动添加桥接方法,确保Processor.process("x")调用仍能正确分派 - 桥接方法对开发者透明,但可通过反射观察到(如
getDeclaredMethods()中看到合成方法)
擦除后无法获取真实类型参数
由于泛型信息完全从字节码中剥离,运行时无法还原原始泛型实参:
-
new ArrayList<String>().getClass() == new ArrayList<Integer>().getClass()返回true -
instanceof List<String>编译失败 —— 泛型类型不可用于运行时类型检查 -
new T[]不合法 —— 因为T在运行时不存在,无法确定数组组件类型

















