2013-06-25 47 views
0

为什么编译器只给出一个警告(“ArrayList是一个原始类型,引用通用类型ArrayList<E>应该参数化”)并编译代码?为什么它不会在运行时给出错误,编译器将无法将我们的数据类型转换为指定的参数类型?为什么编译器允许引用未被参数化的泛型类型?

+0

因为类型是在运行时反正擦除。 –

+1

结合Oli的评论,编译器将用户Object作为类型。 – Leon

回答

1

考虑一个例子时的ArrayList不参数

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 

编译是成功的,因为一般的代码需要在其仿制药未使用的遗留代码兼容。

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

+0

OP已经知道这一点。 OP的问题是为什么编译器允许将原始类型引用赋值给参数化类型。 @Joachim正确回答了下面的问题。 – Santosh

+0

我也用粗体回答了OP的问题。 –

3

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

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

从JLS甲报价(如上面链接):

使用原始类型被允许仅作为让步的遗留代码兼容。强烈建议在将泛型引入Java编程语言之后编写的代码中使用原始类型。未来版本的Java编程语言可能会禁止使用原始类型。

由于太阳不希望引入一个平行宇宙ArrayList和相关的类,它决定添加泛型类型信息的集合(和许多其他地方),并定义了JLS的方式,允许老,非 - 通用代码仍然需要编译(但有警告)。

在编写良好的新代码中,不会与旧的和/或破坏的库原始类型进行交互,这绝不是必需的。

0

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

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

例如如果你传递一个包含所有没有泛型的字符串的集合,那么该方法可能会插入一个不正确的对象。

泛型只有在编译时才可用。编译后,“type erasure”发生,编译器将消除所有泛型。

类型擦除在this link解释。

相关问题