泛型擦除与桥接方法是一体两面:擦除导致运行时类型信息丢失,桥接方法由编译器自动生成以恢复多态,确保编译期类型安全与运行时正确调用。

Java 中泛型擦除与桥接方法是一体两面:擦除是原因,桥接是补救。它们共同保障了泛型代码在编译期有类型安全、运行时仍能正确多态调用。
泛型擦除导致类型信息丢失
Java 泛型只存在于编译期,运行时所有泛型参数都会被“擦掉”:
-
<t></t>→ 擦除为Object -
<t extends number></t>→ 擦除为Number -
List<string></string>、List<integer></integer>→ 运行时都是原始类型List,JVM 完全无法区分
这意味着:
- 无法在运行时通过
instanceof判断list instanceof List<string></string> - 不能
new T()或Class<t></t>直接获取泛型类对象 - 反射中
getGenericReturnType()能拿到泛型签名,但getReturnType()返回的只是擦除后的类型(如Object)
这种设计是为了向后兼容——让 JDK 5 引入泛型后,旧字节码、老框架、第三方库无需修改就能继续工作。
桥接方法是编译器的自动补位机制
当子类重写一个泛型父类或接口的方法,且重写后方法签名因擦除而“不匹配”时,JVM 会认为这不是重写,而是重载,多态就会失效。
例如:
interface Container<t> {
T get();
}
class StringContainer implements Container<string> {
public String get() { return "ok"; }
}</string></t>
擦除后:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 接口方法变成
Object get() - 子类方法是
String get() - 参数和返回类型不一致 → JVM 不认为这是重写 →
Container c = new StringContainer(); c.get()将找不到实现!
编译器于是自动生成一个桥接方法:
public Object get() {
return this.get(); // 转发给 String get()
}
这个方法:
- 签名与擦除后的父类/接口方法完全一致(
Object get()) - 方法体只做类型转换 + 委托(无业务逻辑)
- 字节码中标记为
ACC_BRIDGE | ACC_SYNTHETIC - 源码里看不到,但
javap -v或反射中可见
如何验证桥接方法存在
用反射遍历方法,并用 isBridge() 过滤:
for (Method m : StringContainer.class.getDeclaredMethods()) {
System.out.printf("%s → %s, isBridge: %s%n",
m.getName(),
m.getReturnType().getSimpleName(),
m.isBridge()
);
}
// 输出:
// get → String, isBridge: false
// get → Object, isBridge: true
或者用命令行:
javac StringContainer.java javap -v StringContainer | grep -A 2 -B 2 "bridge"
看到两个 get 方法,descriptor 分别是 ()Ljava/lang/String; 和 ()Ljava/lang/Object;,就确认桥接已生效。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










