java泛型擦除不破坏多态重写,但依赖编译器生成的桥接方法维持契约:父类泛型方法擦除后签名变宽,子类具体实现签名变窄,桥接方法负责类型转换与委托调用,确保jvm能正确识别重写关系。

Java 中泛型擦除机制本身不破坏多态重写,但会让重写关系变得“隐形”——真正起作用的往往不是你写的那个方法,而是编译器悄悄生成的桥接方法(Bridge Method)。
桥接方法是擦除后维持多态的关键补救措施
父类泛型方法被擦除后,签名变“宽”,而子类具体实现的方法签名更“窄”。JVM 按照字节码签名匹配调用,若无桥接方法,子类就无法被识别为合法重写,多态会断裂。
- 父类定义:
public <t> void set(T value)</t>→ 擦除为void set(Object value) - 子类重写:
public void set(String value)→ 这个方法在 JVM 看来签名是set(String),和父类擦除后的set(Object)不一致 - 编译器自动补充:
public void set(Object value)(桥接方法),内部强制转成set((String) value)并委托调用
当你通过父类引用调用时:
Generic<string> ref = new StringGeneric();
ref.set("hello"); // 实际执行的是桥接方法,再跳转到你写的 set(String)</string>
哪些情况会真正构成重写?
必须满足:擦除后方法名、参数类型(原始类型)、返回类型(协变允许)完全一致,且访问权限不降低:
- ✅
public <t> void handle(List<t>)</t></t>和public <u> void handle(List<u>)</u></u>→ 都擦除为handle(List),可重写 - ✅
public void parse(List extends Number>)和public void parse(List<integer>)</integer>→ 都擦除为parse(List),可重写 - ❌
public void process(List<string>)</string>和public void process(List<integer>)</integer>→ 擦除后同为process(List),不能共存于同一类(编译报错,不是重写,是重载冲突)
协变返回类型也靠桥接支撑
接口中 T get() 擦除为 Object get(),子类写 public String get(),编译后同时存在:
- 你写的
String get() - 编译器生成的
Object get()(桥接方法),体内调用(String)get()并返回
外部通过接口调用 get(),命中桥接方法,类型转换由编译器插入,安全透明。
总结一句话:
擦除让源码层面的泛型重写“失真”,但桥接方法在字节码层重建了重写契约——你写的逻辑没变,只是 JVM 调用它时,中间多了一层自动转换的代理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











