声明Generic类型时的编译器警告

时间:2012-01-01 21:39:55

标签: java oop generics scjp

为什么编译器在将变量声明为

时会发出警告
 List<? extends Object> list = new LinkedList();

警告:

Note: ZiggyTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

但是当我将变量声明为

时,它不会发出警告
List<?> list = new LinkedList();

2 个答案:

答案 0 :(得分:2)

如果您使用的是没有类型说明符的集合(例如,Arraylist()而不是ArrayList<String>()),则会出现在Java 5及更高版本中。这意味着编译器无法使用generics以类型安全的方式检查您是否正在使用该集合。

要消除警告,只需具体说明您在集合中存储的对象类型。所以,而不是

List list = new ArrayList();

应该是

List<String> list = new ArrayList<String>();

在您的情况下,如果您按如下方式修改该声明,

List<? extends Object> list = new LinkedList<Object>();

它会在没有警告的情况下编译,因为我们现在使用泛型类型(<Object>)使其类型安全。

答案 1 :(得分:1)

我无法解释为什么编译器不会将这些视为等效,但鉴于它没有,我会尝试解释它拒绝这样做的原因。

第一个(List<? extends Object>)断言List中保存的对象类型是从Object派生的某种未知类型。第二个(List<?>)少说;它只是说列表中对象的类型是未知的。它没有提到任何预期的超类型作为未知类型的上限。

为了验证第一个假设,编译器希望听到您说出在此处构建的List实例中保留的预期类型作为原始类型LinkedList,其中没有说明该主题。但是,如果您要将实例构造为类型LinkedList<Object>,那么您至少可以保证针对该实例的协变读取将与您的断言一致:即,此处的内容列表是某种Object

现在,这一切看起来都很愚蠢,因为Java中的每个引用/非原始类型都扩展了Object,因此List<? extends Object>List<?>之间的解释不应有任何区别。毕竟,第二个意味着第一个,因为语言的类型系统强制要求单根类层次结构。