为什么编译器在将变量声明为
时会发出警告 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();
答案 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<?>
之间的解释不应有任何区别。毕竟,第二个意味着第一个,因为语言的类型系统强制要求单根类层次结构。