泛型与类型擦除
2026/8/24大约 1 分钟
泛型与类型擦除
Java 的泛型是"伪泛型",编译后会被类型擦除替换为原生类型并插入强制转型代码。
什么是类型擦除
Java 语言在 JDK 1.5 之后引入的泛型实际上只在程序源码中存在。编译后的字节码文件中,泛型已被替换为原来的原生类型,并在相应位置插入了强制转型代码。
因此对运行期来说,ArrayList<String> 和 ArrayList<Integer> 是同一个类。
泛型技术是 Java 语言的语法糖,基于类型擦除实现的泛型被称为伪泛型。
反编译示例
// 源码
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "No.1");
System.out.println(map.get(1));// 编译后(反编译结果)
Map map = new HashMap();
map.put(1, "No.1");
System.out.println((String) map.get(1)); // 插入强制转型泛型都变回了原生类型,且 get() 返回处插入了强制转型代码。
类型擦除的后果
方法重载冲突:以下两个方法编译时发生名称冲突——因为擦除后它们的签名完全相同(都是 method(List)):
public void method(List<String> list) { } // 冲突
public void method(List<Integer> list) { } // 冲突:具有相同擦除签名为什么这样设计
- 兼容性:类型擦除让新泛型代码能与 JDK 1.5 之前的旧代码(无泛型)共存
- 代价是丢失了运行期的类型信息(可通过反射获取部分泛型信息,如
ParameterizedType)