列出<! - ? - >或List <object> </object>

时间:2010-11-22 09:44:44

标签: java generics

我有一个方法,其参数应该是“任何事物的列表”。该方法不会修改List的内容。将此方法定义为

更为正确
void foo(List<?> list) {
}

void foo(List<Object> list) {
}

究竟有什么区别?

6 个答案:

答案 0 :(得分:16)

简短回答,使用List<?>,您可以接受List<String>之类的内容,而不会使用List<Object>

官方泛型跟踪herehere对此进行了讨论。

  

[...]这是使用泛型(以及新的for循环语法)编写它的天真尝试:

   void printCollection(Collection<Object> c) {
       for (Object e : c) {
           System.out.println(e);
       }
   }
     

问题是这个新版本比旧版本更有用。虽然可以使用任何类型的集合作为参数调用旧代码,但新代码只需要Collection<Object>,正如我们刚才演示的那样,它不是各种集合的超类型!   那么各种收藏品的超类型是什么?它写成Collection<?>(发音为“未知集合”),即元素类型与任何东西匹配的集合。由于显而易见的原因,它被称为通配符类型。我们可以写:

   void printCollection(Collection<?> c) {
       for (Object e : c) {
           System.out.println(e);
       }
   }
     

现在,我们可以使用任何类型的集合来调用它。

答案 1 :(得分:1)

两者完全不同

void foo(List<?> list)

表示您希望列出某些内容,但尚未指定它是什么

void foo(List<Object> list)

说你希望传递的列表是一个对象列表,所以如果你试图传递一个List,它就不会被接受(而不是第一个声明)

一个常见的错误是假设List<String>子类型,所以说List<Object>即使String是对象的suptype也不是这种情况。

答案 2 :(得分:1)

List<Object>已参数化类型Object,这实际上意味着您可以在列表中添加所有对象。

但是,List<?>表示未知数列表。只要您不打算在列表中添加任何内容,它与List<Object>基本相同,但您必须担心以下情况:

List<?> unknownList = new ArrayList<String>();
unknownList.add(new Object()); //Compilation error.

?(在本例中)表示您只能添加String的值或String的子类型。

如果您只想迭代列表并检索值,List<?>List<Object>基本相同。

更多信息here

答案 3 :(得分:0)

如果您不想修改列表,则List<?>更适合。

这样你就可以通过e。 G。 <{1}}和List<String>到您的方法。

答案 4 :(得分:0)

您需要void foo(List<?> list),否则您将无法传递List<String>

如果您使用void foo(List<Object> list),那么您只能传递List<Object>

这是因为,在Java中,泛型不是covariantList<String>不是List<Object>的子类型。

答案 5 :(得分:0)

本教程的第3节和第4节应该回答您的问题:

http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

从教程中引用:

  

通常,如果Foo是Bar的子类型(子类或子接口),并且G是一些泛型类型声明,则不是G&lt; Foo&gt;的情况。是G&lt; Bar&gt;的亚型。 ....

     

...集合&lt; Object&gt;,正如我们刚刚演示的那样,它不是各种集合的超类型!   那么各种收藏品的超类型是什么?它写成Collection&lt;?&gt; (发音为“collection of unknown”),即元素类型与任何内容匹配的集合。

但是,根据严格假设方法foo将使集合保持不变,实现应该没有区别。