桥接方法是编译器为修复泛型擦除导致的多态断裂而自动生成的适配方法,签名匹配父类擦除后形式(如object get()),内部调用子类真实方法(如string get()),并标记acc_bridge与acc_synthetic。

桥接方法不是你写的,而是编译器在泛型继承或实现泛型接口时,为修复类型擦除导致的多态断裂,悄悄加进去的“适配桩”。它不改变业务逻辑,只确保 JVM 能按预期调用到子类的真实方法。
泛型擦除是桥接方法出现的前提
Java 泛型只在编译期存在,运行时所有类型参数都会被擦除:
-
接口 Comparable
擦除后变成 Comparable,其中int compareTo(T)变成int compareTo(Object) -
类 Integer implements Comparable
中你写的 public int compareTo(Integer),擦除后仍是compareTo(Integer),参数类型没变回 Object - JVM 只认字节码签名:方法名 + 参数类型 + 返回类型。此时
compareTo(Object)和compareTo(Integer)是两个不同方法 → 不构成重写 → 多态失效
编译器怎么决定生成桥接方法
当满足以下全部条件时,javac 就会插入桥接方法:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 父类或接口中定义了带泛型的方法(如
T get()或void set(T)) - 子类/实现类将泛型具体化(如写成
String get()或void set(String)) - 擦除后,子类方法签名与父类擦除后的签名不一致(参数类型或返回类型不同)
- 该方法需支持通过父类/接口引用进行多态调用(即语义上必须是“重写”)
桥接方法长什么样、干了什么
以 Box<t></t> 和 StringBox extends Box<string></string> 为例:
- 你写的:
public String get() - 父类擦除后:
Object get() - 编译器生成的桥接方法:
public Object get() {
return this.get(); // 调用你的 String get(),隐式转为 Object
}
这个方法有三个关键特征:
- 签名完全匹配父类擦除后的形式(无参、返回
Object) - 方法体只做一件事:调用你写的那个真实方法,并处理类型协变(返回值强转)或参数窄化(入参强转)
- 字节码中标记为
ACC_BRIDGE | ACC_SYNTHETIC,反射中可通过method.isBridge()识别
为什么不能省略桥接方法
没有它,JVM 在运行时就找不到符合接口契约的实现:
- 比如把
StringBox放进List<box>></box>,再通过Box.get()调用,JVM 会查找Object get()—— 若无桥接方法,就会调用Box的抽象方法或抛异常 - 类似地,
TreeSet<integer></integer>依赖Comparable.compareTo(Object),若Integer没有桥接方法,比较过程会失败 - 桥接方法让“逻辑重写”在字节码层面真正成立,是泛型与 JVM 兼容性的底层保障
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










