桥接方法是编译器自动生成的合成方法,用于解决泛型擦除后子类方法签名与父类不一致导致的重写失效问题;其本质是转发调用并处理类型协变,标记为acc_bridge | acc_synthetic。

Java 中桥接方法(Bridge Method)不是手动写的,而是编译器在泛型继承或实现泛型接口时,自动插入的合成方法,目的只有一个:让擦除后的 JVM 字节码仍能正确支持多态调用。
它出现的前提是——子类重写的方法签名,因泛型擦除而与父类/接口擦除后的方法签名不一致。这时 JVM 无法识别为“重写”,编译器就悄悄补一个“适配层”。
桥接方法生成的核心逻辑
- 父类或接口中定义了泛型方法,比如
public T get()或public void set(T value) - 子类或实现类将
T具体化,比如写成public String get()或public void set(String value) - 编译后,泛型被擦除:
- 父类方法变成
Object get()/void set(Object value) - 子类方法变成
String get()/void set(String value)
- 父类方法变成
- JVM 只看字节码签名:参数类型、返回类型、方法名。两者不一致 → 不构成重写 → 多态失效
- 编译器检测到这种“逻辑上应重写,但擦除后签名错位”的情况,就生成桥接方法
桥接方法长什么样?
以 Box<t></t> 和 StringBox extends Box<string></string> 为例:
abstract class Box<t> { abstract T get(); }
class StringBox extends Box<string> { public String get() { return "ok"; } }</string></t>
编译后,StringBox 类中实际存在两个 get 方法:
- 你写的:
public String get() - 编译器加的桥接方法:
public Object get() { return this.get(); // 转发,隐式强转 String → Object }
这个桥接方法具备以下特征:
- 方法名和参数列表完全匹配父类擦除后的签名(这里是无参、返回
Object) - 方法体只做一件事:调用你写的那个具体方法,并处理返回类型协变(或参数窄化)
- 字节码里标记为
ACC_BRIDGE | ACC_SYNTHETIC(用javap -v可见) - 在反射中会暴露出来,但
method.isBridge()返回true
哪些场景会触发桥接方法?
- 子类重写泛型父类的方法参数类型被具体化(如
T→String) - 子类重写泛型父类的返回类型被具体化(如
T→Integer),且擦除后与父类返回类型不兼容(如NumbervsInteger) - 实现泛型接口时,方法签名因类型擦除产生不匹配(如接口
Comparable<t>.compareTo(T)</t>擦除为compareTo(Object),而实现类写compareTo(Integer)) - 使用泛型上界(如
<t extends number></t>)后,子类返回Integer,父类擦除为Number,也会生成桥接方法来适配返回类型
不会生成桥接方法的情况
- 子类方法签名擦除后与父类完全一致(例如都擦成
Object,且你也没改参数或返回类型) - 方法没加
@Override,或根本没参与继承/实现关系(纯静态工具方法、私有方法等) - 泛型仅用于字段或局部变量,未出现在方法签名中
桥接方法是编译器默默做的“翻译工作”,它不改变业务逻辑,也不增加运行开销,只是确保你在写 list.add("hello") 时,哪怕 list 是 List<string></string> 类型,背后依然能走对子类实现——靠的就是这个看不见却关键的转发跳板。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











