Java 泛型**“类型擦除(Type Erasure)”**的根本原因,可以一句话概括:
为了兼容旧版本 Java(JDK 1.0–1.4),同时避免修改 JVM,Java 选择在编译期擦除泛型信息。
下面从几个关键角度解释为什么要擦除,以及它带来的代价。
Java 在 JDK 5(2004) 才引入泛型,但在此之前已经有大量代码:
List list = new ArrayList();
list.add("abc");
如果泛型是真实存在于运行时(像 C# 那样),那么:
ArrayList 的 .class 文件)无法运行为了做到二进制兼容(Binary Compatibility):
✅ 旧代码能继续跑
✅ 新代码能用泛型
✅ JVM 不需要改动
→ 唯一可行的方案:编译后擦除
Java 泛型是 编译期特性:
List<String> list = new ArrayList<>();
编译后变成:
List list = new ArrayList();
并自动插入强制转换:
String s = (String) list.get(0);
所以:
StringC# 的泛型是 运行时泛型(reified generics):
List<string>
List<int>
在 CLR 中是不同类型。
Java 如果这么做需要:
Sun 当时明确选择:稳定 > 完美
new ArrayList<String>().getClass()
== new ArrayList<Integer>().getClass()
new T()T obj = new T(); // ❌ 编译错误
T[] arr = new T[10]; // ❌
void test(List<String> l) {}
void test(List<Integer> l) {} // ❌ 擦除后签名相同
Java 用一些“补丁”缓解问题:
Class<T> 参数传递Type(ParameterizedType)? extends / superJava 泛型擦除,不是技术最优解,而是工程妥协:用编译期安全,换取 JVM 稳定和历史兼容。
如果你愿意,我也可以讲:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。