java泛型擦除后无界类型默认为object,因其是所有引用类型的公共直接父类且无额外语义约束;有上界时取最左具体类或接口,确保字节码兼容与类型安全。

Java 中 Object 类在泛型擦除后不是“被替换成 Object”,而是——它本身就是擦除的默认目标。
无边界泛型一律擦除为 Object
当声明如 <t></t>、<e></e> 这类没有 extends 限定的泛型参数时,编译器直接将其替换为 Object。这不是运行时“转换”,而是编译期字节码层面的彻底替换:
-
public class Box<t> { private T value; }</t>→ 编译后等价于private Object value; -
public <t> T getFirst(T[] arr)</t>→ 擦除为public Object getFirst(Object[] arr) - 所有对
T的读写操作,在字节码中都按Object处理,不保留任何子类型痕迹
Object 是擦除的起点,不是运行时的“包装”
很多人误以为泛型对象“还是原来的类型,只是被 Object 包了一层”。实际并非如此:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- JVM 加载的
.class文件里不存在Box<string></string>这个类,只有Box(原始类型) -
new ArrayList<string>()</string>和new ArrayList<integer>()</integer>的getClass()返回同一个Class>实例 - 方法签名中的
T在字节码中就是Object,调用处插入的强制转换(如(String) box.get())由编译器生成,非 JVM 动态识别
为什么选 Object?兼容性与单根继承结构决定的
Java 所有类都直接或间接继承自 Object,这使它成为最安全的擦除锚点:
- 确保擦除后仍能存放任意引用类型实例,不破坏原有容器逻辑
- 避免引入新底层类型,维持 JVM 字节码指令集不变(如
aload/astore仍操作Object引用) - 与 JDK 1.5 前的“裸
Object容器”完全二进制兼容,老代码无需重编译即可调用泛型类
注意:有上界时不会擦成 Object
若泛型带约束,擦除目标就不再是 Object:
-
<t extends number></t>→ 擦除为Number,不是Object -
<t extends comparable>></t>→ 擦除为Comparable(首个上界) - 此时字段/返回值类型在字节码中是
Number,而非Object;但依然丢失具体子类型(如Integer或Double)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










