桥接方法是编译器为解决泛型擦除导致的签名不匹配而自动生成的bridge synthetic方法,它通过参数强制转换调用子类真实方法,确保jvm动态分派仍走子类逻辑,并带acc_bridge和acc_synthetic标志。

桥接方法不是你写的,但它让多态在泛型场景下依然成立——关键在于编译器悄悄补上了一个“签名对齐层”,让JVM能按擦除后的规则找到子类逻辑。
为什么父类引用调用时不会跳过子类?
泛型擦除后,父类方法签名变成原始类型(比如 setValue(Object)),而子类重写的方法签名是具体类型(比如 setValue(Date))。JVM只认字节码签名,二者不一致就构不成重写,多态会失效。桥接方法正是为解决这个断层而生。
- 编译器检测到子类标注了
@Override,但擦除后签名不匹配,就自动生成一个桥接方法 - 该方法名和参数类型完全复刻父类擦除后的签名(如
public void setValue(Object obj)) - 方法体只做一件事:强制转换参数,再调用你写的子类真实方法(如
setValue((Date) obj)) - JVM 方法表里,这个桥接方法占据原本父类方法的位置,确保动态分派走的是子类逻辑
桥接方法如何参与运行时调用链?
当你用父类引用调用方法时,整个流程是透明的:
-
Pair<date> p = new DateInter();</date>—— 编译后等价于Pair p = new DateInter(); -
p.setValue(new Date());—— JVM 查找setValue(Object),命中桥接方法 - 桥接方法执行
this.setValue((Date) obj),最终调用你定义的setValue(Date) - 如果传入非法类型(如
new Object()),会在桥接方法里抛ClassCastException,而不是静默失败
怎么确认桥接方法真实存在?
它不出现在源码里,但字节码中清晰可查:
- 用
javap -c -p DateInter.class反编译,能看到两个setValue方法 - 一个是你的
public void setValue(Date),另一个标记为bridge synthetic - 反射中可通过
method.isBridge()判断是否为桥接方法 - 桥接方法在字节码中带有
ACC_BRIDGE和ACC_SYNTHETIC标志
协变返回类型也依赖桥接方法
不只是参数类型,返回类型协变同样需要桥接支持:
- 父类方法擦除后返回
Object,子类重写返回Date - 编译器生成桥接方法
public Object getValue(),内部调用return this.getValue(); - 返回值自动转型,语义由子类方法主导,JVM 只看到标准的重写结构
- 这种机制让
Comparable<string></string>的compareTo(String)能被Object引用正常调用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











