2012-01-01 379 views
4

为什么编译器问题的变量声明为编译器警告

时警告
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

结帐http://stackoverflow.com/questions/8683137/and-extends-object/8683314和我的答案中的优秀泛型教程那里是一个必须阅读时使用泛型 – Robin 2012-01-01 21:48:01

+0

它不发布任何减少正如你在NetBeans 6.9.1中用jdk 6所提到的那样。 – Lion 2012-01-01 22:01:47

+0

我没有使用IDE。从命令行提示编译时,是否会收到警告? – ziggy 2012-01-01 22:15:33

回答

1

我无法解释为什么编译器不会将这些视为等价的,但假定它不这样做,我会试着解释它为什么拒绝这么做。

第一个(List<? extends Object>)声称List中保存的对象的类型是来自Object的某种未知类型。第二个(List<?>)说少;它只是说列表中的对象的类型是未知的。它没有提及任何预期的超类型作为未知类型的上界。

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

现在,这一切似乎都傻了,因为Java中的每个参考/非原始类型扩展Object,所以不应该在List<? extends Object>List<?>之间的理解上发生歧义;毕竟,第二个意味着第一个意义上的,因为语言的类型系统的授权单根分类阶层。

2

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

要摆脱警告,只需具体说明要在集合中存储什么类型的对象。所以,与其

List list = new ArrayList(); 

应尽可能

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

在你的情况,如果你修改声明如下,

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

将与任何警告,因为编译我们现在使用通用类型(<Object>)来使其类型安全。

+0

'新的LinkedList <?扩展对象>();'不编译 – Robin 2012-01-01 21:50:47

+0

除了你不能在声明中使用通配符.. – Voo 2012-01-01 21:51:19