我有一个方法,其参数应该是“任何事物的列表”。该方法不会修改List的内容。将此方法定义为
更为正确void foo(List<?> list) {
}
或
void foo(List<Object> list) {
}
究竟有什么区别?
答案 0 :(得分:16)
简短回答,使用List<?>
,您可以接受List<String>
之类的内容,而不会使用List<Object>
。
[...]这是使用泛型(以及新的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中,泛型不是covariant:List<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将使集合保持不变,实现应该没有区别。