为什么编译器允许引用未参数化的泛型类型?

时间:2013-06-25 06:38:37

标签: java generics raw-types

为什么编译器只发出警告(&#34; ArrayList是原始类型。对泛型ArrayList<E>的引用应该参数化&#34;)并编译代码?为什么它没有给出错误,因为在运行时编译器将无法将数据类型转换为指定的参数类型?

3 个答案:

答案 0 :(得分:3)

对不带参数的泛型类型的引用称为raw types

编译器允许使用它们的唯一原因是向后兼容性:每一代Java编译器都试图尽可能向后兼容旧代码。而且,由于Java 5中引入了泛型,许多旧代码根本就没有使用它们。

JLS的引用(如上所述):

  

原始类型的使用仅允许作为遗留代码兼容性的让步。在将泛型引入Java编程语言之后编写的代码中使用原始类型是非常不鼓励的。未来版本的Java编程语言可能会禁止使用原始类型。

由于Sun不想将并行Universe引入ArrayList及相关类,因此决定将通用类型信息添加到集合(以及许多其他地方)并以允许旧的方式定义JLS,仍然要编译的非通用代码(但是会发出警告)。

在编写良好的代码中,永远不需要与旧的和/或破坏的库原始类型接口的新代码。

答案 1 :(得分:1)

考虑一个没有参数化的arraylists的例子

 ArrayList listOfObjects = new ArrayList();

 listOfObjects.add("someStringValue");
 listOfObjects.add(new Integer(10));
 listOfObjects.add(new Dog());

此处的所有内容都有效,因此您可以在listOfObjects中添加任何内容。

但如果你参数化,

 ArrayList<String> listOfStrings = new ArrayList<String>();
 listOfStrings.add("someStringValue");
 listOfStrings.add(new Dog()); // Boom, compiler error, can't add dogs into list of strings

编译成功,因为通用代码需要与不使用泛型的遗留代码兼容。

运行时也没有类型安全性,

答案 2 :(得分:0)

在Java中引入了泛型,以提供集合的一致性。

即。如果您将一个集合传递给没有泛型的方法,那么该方法将不知道从集合中检索元素时会发生什么。

e.g。如果你传递一个包含所有字符串而没有泛型的集合,那么该方法可能会在其中插入一个不正确的Object。

泛型只有在编译之前才可用。编译后,“type erasure”发生,所有泛型都被编译器消失了。

类型擦除在this link中解释。