桥接方法是编译器为解决泛型擦除或协变返回导致的签名不匹配而自动生成的合成方法,它保持父类擦除后的方法签名,内部强制转型调用子类真实方法,字节码中标记为acc_bridge和acc_synthetic。

Java中泛型方法在编译后不会保留类型参数,而是被擦除为上界(通常是Object),这时若子类重写泛型父类或接口中的方法,其签名可能与擦除后的父类方法不一致——编译器就会自动生成桥接方法(Bridge Method)来补全多态调用链。它不是你写的,也不出现在源码里,但真实存在于字节码中,且对运行时行为至关重要。
泛型擦除导致签名不匹配
比如父类定义:class Pair<t> { public T getValue() { ... } }</t>
擦除后变成:public Object getValue()
而子类重写为:class DatePair extends Pair<date> { @Override public Date getValue() { ... } }</date>
擦除后实际是:public Date getValue()
这和父类擦除后的Object返回类型不一致,JVM认为这不是重写,而是重载——多态就失效了。
编译器自动插入桥接方法
为修复这个问题,javac会在DatePair.class中生成一个合成的桥接方法:
- 方法名、参数列表、返回类型完全匹配父类擦除后的签名(如
public Object getValue()) - 方法体只做一件事:强制转型后调用你写的那个真实方法(如
return (Date) this.getValue();) - 字节码中带
ACC_BRIDGE | ACC_SYNTHETIC标记,表示这是编译器生成的适配层
如何确认桥接方法存在
不能靠看源码,得查编译结果:
- 用
javac DatePair.java编译 - 执行
javap -v DatePair,搜索bridge或synthetic - 对比两个
getValue方法的descriptor:一个是()Ljava/util/Date;,另一个是()Ljava/lang/Object; - 在反射中调用
method.isBridge()可直接识别
不止于泛型:协变返回也触发桥接
即使没用泛型,只要子类重写时缩小了返回类型,也会生成桥接方法。例如:
- 父类:
Animal getPet() { ... } - 子类:
@Override Dog getPet() { ... } - 编译器会加一个
public Animal getPet()桥接方法,内部返回(Animal) super.getPet()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











