jvm 为什么在运行时需要java类型擦除?

8wtpewkr  于 2022-11-07  发布在  Java
关注(0)|答案(1)|浏览(221)

以下是java documentation here的摘录
由于类型擦除,List<Number>List<String>都变成了List。因此,编译器允许将具有原始类型List的对象l赋值给对象ls。
也来自同一文档
请考虑以下示例:

List l = new ArrayList<Number>();
List<String> ls = l;       // unchecked warning
l.add(0, new Integer(42)); // another unchecked warning
String s = ls.get(0);      // ClassCastException is thrown

在类型擦除期间,类型ArrayList和List分别变为ArrayList和List。
为什么编译器不能将其显示为错误(而不是警告)。有人能提供一个需要警告的示例吗?当警告变成错误时,警告会导致问题(或使某些有用的模式无法使用)。

nnsrf1az

nnsrf1az1#

Java在java 1.5中获得了类型变量。在java 1.5之前,它们不存在
Java也非常不喜欢发布新的版本,因为“升级”比“简单地用新的编译器编译你现有的代码,它就像以前一样工作”更复杂。而且,“你可以运行用java 1.4的javac编译的代码,在1.5的java.exe上运行,它运行得很好”。
为什么呢?因为如果不这样做,你会得到一个分裂的社区,而且因为大多数项目使用500个依赖项,这是非常有害的。你不能从java 1.4“升级”到1.5,直到这500个依赖项中的每一个都升级了。
合并这两个事实和泛型是有意义的:

  • 为什么要擦除呢?因为除此之外它还能如何工作呢?源自javac1.4的类文件不可能有泛型信息,因为在javac1.4发布时它们并不存在!
  • 为什么要使用“原始类型”呢?因为前泛型代码本身就有这些类型(List<T>在java 1.4上会是一个编译器错误),而且从本质上讲,typevar方面 * 是不 * 健全的。你可以这样写:
List foo = new ArrayList();
foo.add(5);
foo.add("hello");

并且它在javac1.4上编译得很好。因此它必须在javac1.5上编译。作为一种折衷,如果您试图在javac1.5上编译它,它会工作并生成一个行为完全相同的类文件,但您 * 确实 * 会收到警告。
java 1.5已经有25年历史了,所以现在看起来很奇怪,很过时。但是你问的是“为什么”,这就是为什么。

相关问题