桥接方法是编译器为弥补泛型擦除导致的多态断裂而生成的合成方法,它通过添加符合擦除后父类签名的委托方法(如Object get()→调用String get()),使协变返回和参数特化在JVM层面仍能正确多态调用。

桥接方法本身不“支持”协变返回类型,而是为保障泛型擦除后仍能正确实现协变返回(以及参数类型特化)提供底层机制。它不是设计来增强特性,而是弥补类型擦除带来的多态断裂。
为什么泛型擦除会导致协变失效
Java泛型在编译后全部擦除:泛型参数 T 变成 Object,泛型方法签名被“降级”。例如:
- 接口:
interface Box<t> { T get(); }</t>→ 擦除后变成Object get(); - 实现类:
class StringBox implements Box<string> { public String get() { ... } }</string>→ 擦除后仍是public String get()
此时,StringBox 并未真正重写接口的 Object get() 方法(因为方法签名不同:返回类型 String ≠ Object),导致接口引用无法多态调用——这违反了面向对象的基本契约。
桥接方法如何补上这个缺口
编译器自动在 StringBox 中生成一个合成的桥接方法:
-
public Object get() { return this.get(); }(桥接方法,标记为ACC_BRIDGE | ACC_SYNTHETIC) - 它满足接口要求的签名(返回
Object),又内部委托给真实的String get() - 运行时通过接口变量调用
get(),实际执行的是桥接方法,再跳转到子类特化版本
这样,外部看到的是协变语义(调用 Box<string></string> 得到 String),底层靠桥接维持了字节码兼容与多态连通。
协变返回类型与桥接的协同关系
协变返回是语言特性(JDK 5+ 允许子类缩小返回类型),而桥接是其实现手段之一:
- 没有泛型时,纯协变(如
Animal get()→Dog get())不需要桥接,JVM 原生支持 - 一旦涉及泛型,擦除使父类/接口方法签名“变宽”,子类特化方法就变成“非重写”,必须靠桥接来伪造重写关系
- 所以:协变返回是目标,桥接方法是达成该目标在泛型场景下的必要桥梁
实际判断与调试提示
可通过反射识别桥接方法:
-
method.isBridge()返回true即为编译器生成的桥接方法 - 反编译 class 文件可见
ACC_BRIDGE标志,且方法体通常只含强制转型和委托调用 - Spring、MyBatis 等框架在属性内省(Introspection)时若忽略桥接方法,可能误判 getter/setter 配对,引发
PropertyNotFoundException类错误

















