为什么Java编译器知道你想用数组做什么,但不知道你想用泛型做什么?

时间:2016-10-24 07:12:13

标签: java generics

我正在阅读Thinking in Java第4版,在章节泛型中,我发现了这些句子: 这一段解释了为什么数组支持协方差,但泛型不支持协方差。

  

真正的问题是我们在讨论容器的类型,   而不是容器所持有的类型。与数组不同   泛型没有内置协方差。   这是因为数组完全是用语言定义的   因此内置了编译时和运行时检查,但有   泛型,编译器和运行时系统无法知道你想要什么   你的类型和规则应该是什么。

但是我真的不明白这个段落意味着什么,为什么编译器知道你想用数组做什么但是不知道你想用泛型做什么?任何人都可以举个例子吗?

2 个答案:

答案 0 :(得分:2)

首先,引用目前尚不清楚。数组和泛型都是用语言完全定义的,尽管是以不同的方式。编译器和运行时系统都无法读懂你的想法,因此不知道你想要对你的类型做什么"。

引用似乎指的是数组是有效的,而泛型不是:在运行时,List的元素类型是未知的,但数组的元素类型是。也就是说:在运行时,List<String>List<Integer>都具有相同的类型(List),而String[]Integer[]都有不同的类型。但是,在编译时,List<String>List<Integer>是不同的类型。

其原因主要是历史原因。在第一个版本的Java中引入了数组,并且没有理由使运行时已知数组的元素类型。但是,当在Java 5中引入泛型时,目标是使新的Java代码与旧的Java代码兼容(反之亦然),因此必须在运行时擦除泛型。

答案 1 :(得分:1)

为了支持遗留代码,较新版本的Java允许类型安全的代码与旧代码一起使用。在创建字节码时,Java编译器将所有类型安全的声明替换为相关的强制转换(如果不存在类型参数,则转换为Object)。因此,生成的字节码仅包含普通的类,接口和方法。这称为类型擦除。 (所有这些麻烦只是为了支持遗留代码)。

您可以在我的博客here找到详细说明。