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