java多态在泛型擦除后仍能正常工作,靠的是编译器生成的桥接方法:它严格匹配擦除后的父类/接口签名(如object feed(list)),内部转发调用真实方法(如string feed(list)),并带acc_bridge标记,确保jvm动态分派正确指向子类逻辑。

Java 多态在泛型擦除后依然能正常工作,靠的不是运行时保留类型信息,而是编译器提前埋下的“适配层”——桥接方法。它不改变 JVM 的规则,而是在字节码层面悄悄补全被擦除破坏的方法签名一致性,让多态调用在运行时仍能正确分派。
类型擦除如何威胁多态基础
多态依赖“方法签名一致”才能完成动态绑定。但泛型擦除会改写签名:
- 接口
Species<t></t>声明T feed(List<string>)</string>,擦除后变成Object feed(List) - 子类
Dog显式实现String feed(List<string>)</string>,擦除后是String feed(List) - 此时 JVM 看到:接口要
Object feed(List),子类却只提供String feed(List)—— 返回类型不同,不满足重写契约
桥接方法就是那个“自动转发的中间人”
编译器检测到这种签名断层,就生成一个不可见的桥接方法,严格匹配擦除后的父类/接口签名:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 自动生成:
public Object feed(List list) { return this.feed(list); } - 这个方法有
ACC_BRIDGE和ACC_SYNTHETIC标记,反射可见但源码不可见 - 它把擦除后的调用(如
species.feed(someList))安全转发给真实的业务方法
运行时多态调用的实际链条
当你写 Species<string> s = new Dog(); s.feed(...)</string>,JVM 执行的是:
- 查虚方法表(vtable),找到
feed(List)对应的入口 - 该入口指向桥接方法(因它是唯一符合擦除后签名的
feed(List)) - 桥接方法内部强制转型并调用你写的
String feed(List<string>)</string> - 返回值再按需转为
Object,满足接口契约
怎么确认和处理桥接方法
反射中常看到两个同名方法,用 Method.isBridge() 可精准识别:
-
true:编译器注入,仅用于多态适配,不应直接调用或参与逻辑判断 -
false:你写的实际方法,含真实业务逻辑 - 做反射遍历时建议过滤掉桥接方法,避免重复处理或类型误判
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










