桥接方法是编译器为修复泛型擦除导致的多态断裂而自动生成的适配器,其签名匹配擦除后父类/接口方法(如Object get()),内部强制转换并委托调用子类真实方法(如String get()),带ACC_BRIDGE和ACC_SYNTHETIC标志,确保JVM动态分派正确指向子类逻辑。

桥接方法是编译器为弥合泛型擦除与多态语义之间的断层,在字节码层面自动插入的转发适配器。它不改变业务逻辑,只确保 JVM 能按预期完成方法分派。
为什么擦除后必须有桥接方法
Java 泛型在编译后全部擦除:<T> 变成 Object,List<String> 变成 List,接口或父类中声明的 public T get() 擦除为 public Object get();而子类实现的 public String get() 擦除后仍是 public String get() —— 返回类型不同,JVM 认为这不是重写,而是独立方法。没有桥接方法,通过父类引用调用时就会找不到实现,直接失败。
桥接方法在字节码中的真实样子
它是一个编译器生成的合成方法,特征非常明确:
- 方法名、参数类型、返回类型完全匹配父类/接口擦除后的签名(如 public Object get() 或 public void set(Object))
- 方法体只做一件事:强制类型转换 + 委托调用你写的实际方法(如 return this.get(); 或 this.set((String) obj);)
- 字节码中带有 ACC_BRIDGE 和 ACC_SYNTHETIC 标志,javap -v 可见,但源码里不可见
- 不能被 Java 源码覆盖或调用,仅用于运行时方法分派
什么情况下会触发生成
不是所有泛型重写都产生桥接,必须同时满足:
立即学习“Java免费学习笔记(深入)”;
- 父类或接口方法含泛型参数(如 <T> T get() 或 void put(T item))
- 子类/实现类将泛型具体化(如 String get() 或 void put(String s))
- 擦除后,子类方法签名与父类擦除签名不一致(参数类型或返回类型不同)
- 该方法被设计为可多态调用(即外部可能通过父类/接口引用访问)
怎么确认它真的存在
不能看源码,得看编译结果:
- 用 javac 编译后,执行 javap -v YourClass,搜索 bridge 关键字,比对 descriptor 字段(比如 (Ljava/lang/Object;)Ljava/lang/Object; vs (Ljava/lang/String;)Ljava/lang/String;)
- 用反射获取所有方法,对每个 Method 调用 isBridge() 判断——返回 true 就是桥接方法
- 注意:getDeclaredMethods() 通常会返回两个同名方法,一个是你写的,一个是桥接的,靠 isBridge() 区分


















