桥接方法是编译器为修复类型擦除导致的重写断裂而自动生成的合成方法,确保子类特化方法(如String get())能正确重写父类擦除后签名(Object get()),维持多态调用正确路由。

桥接方法是编译器在泛型类型擦除后,为修复因签名不匹配导致的重写断裂而自动生成的辅助方法。它不写在源码里,却真实存在于字节码中,确保多态调用仍能正确路由到你写的那个具体方法。
类型擦除破坏了方法签名一致性
Java 泛型在编译期被擦除:所有类型参数 T 默认替换成 Object(或其上界),方法签名随之改变。比如:
- 泛型父类定义:
abstract class Box<T> { abstract T get(); }→ 擦除后变成abstract Object get(); - 子类实现:
class StringBox extends Box<String> { public String get() { return "ok"; } }
问题来了:子类的 String get() 和父类擦除后的 Object get() 参数列表相同但返回类型不同(String ≠ Object),JVM 认为这不是重写,而是重载——多态就断了。
编译器插入桥接方法补全重写关系
为让 JVM 能识别“这是重写”,编译器悄悄在 StringBox 中生成一个桥接方法:
立即学习“Java免费学习笔记(深入)”;
- 方法名和参数完全匹配擦除后的父类签名:
public Object get() - 方法体只做一件事:
return this.get();(隐式将String强转为Object) - 字节码中标记为
ACC_BRIDGE | ACC_SYNTHETIC,反射中可通过method.isBridge()识别
哪些情况一定会触发桥接方法生成
只要子类或实现类对泛型父类/接口的方法做了“类型特化”,且特化后与擦除签名不一致,编译器就会加桥接方法。典型场景包括:
- 重写泛型父类方法时,返回类型从
T变成具体类型(如String),且擦除后与父类返回类型不兼容(如父类擦除为Number,子类返回Integer) - 实现泛型接口时,方法参数从
T改为具体类型(如接口Comparable<T>.compareTo(T)擦除为compareTo(Object),而实现类写compareTo(Integer)) - 子类重写泛型父类的带参方法,参数类型被具体化(如父类
<T> void set(T t)擦除为void set(Object o),子类写void set(String s))
桥接方法让多态在运行时依然成立
当你用父类或接口引用调用方法时,JVM 查找的是擦除后的签名:
Box<String> b = new StringBox();-
b.get();→ JVM 在StringBox中查找Object get()→ 找到桥接方法 → 调用并转发到String get()
整个过程对开发者透明,但正是这个“看不见的转发者”,撑起了泛型代码的多态能力。


















