List和List<?>的区别

4

我已经阅读了很多相关内容,我知道:

List<Object> listOfObject = new ArrayList<TYPE>();   // (0)
//can only work for TYPE == Object.
//if TYPE extends Object (and thus objects of type TYPE are Objects),
//this is not the same with Lists: List<Type> is not a List<Object>

现在我已经读到以下内容是可以的:

List undefinedList = new ArrayList<TYPE>();   // (1)
//works for ANY type (except for primitives)

并且
List<?> wildcardList = new ArrayList<TYPE>();   // (2)  
//also works for ANY type (except for primitives)

然后:

List undefinedlist = new ArrayList(); //no TYPE specified
undefinedList.add(new Integer(1)); //WORKS
undefinedList.add(new String("string")); //WORKS

然而:
List<?> wildcardList = new ArrayList<TYPE>(); //TYPE specified
wildcardList.add(new TYPE(...)); //COMPILER ERROR

例子:
List<?> wildcardList = new ArrayList<String>(); //TYPE specified
wildcardList.add(new String("string")); //COMPILER ERROR: The method add(capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (String)

我理解为什么你不能向wildcardList添加任何东西,因为它的类型可以是任何东西。然而,为什么可以向undefinedList添加内容呢?? 鉴于(1)和(2),它们看起来相同并且表现相同。


与几乎任何问题一样,最好实际展示“编译器错误”的文本(错误信息的文本)。 - billjamesdev
?并不意味着任何东西,而是表示未知 - m0skit0
我猜你还没有阅读这个链接吧?http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html - Duncan Jones
@DuncanJones:是的,我做了,但是它并没有解答我的问题。 - joost
@joost 这解释了你的一个问题。搜索“由于我们不知道 c 的元素类型,因此无法向其添加对象”。 :-) - Duncan Jones
@DuncanJones 在我第一篇帖子中,我说过:我理解为什么你不能向通配符列表 wildcardList 添加任何东西,因为它的类型可以是任何东西。 - joost
6个回答

4
List undefinedListList<?> wildcardList不同,正如你自己发现的那样。第一个是原始类型,第二个是无界通配符。
如果您想使用泛型类型但不知道或不关心实际类型参数是什么,请使用无界通配符。在此列表中,除了null之外,您无法放置任何内容,并且您所知道的有关从中获取元素的信息就是它们扩展Object(实际上,List<?>List<? extends Object>相同)。无界通配符很有用,因为如果您天真地将某些东西声明为List<Object>,则无法将例如List<String>分配给它,而您可以将List<String>分配给List<?>
您几乎永远不需要使用原始类型,它们仅可用于与Java 5之前编写的代码兼容。

2
List<?>被解读为一种未知类型的列表。作为程序员,您不能做出任何对该类型的假设,并且不能将任何东西放入此类集合中,除了null。但是您可以放心使用此列表,因为编译器会为您保证类型安全。 List基本上称为原始类型。也就是说,它已经选择放弃编译器所保证的类型安全。因此,您可以将任何类型的元素放入该列表中,从而破坏其不变性。请不要再使用原始类型进行编码了。它们基本上是为向后兼容而支持的,因为在Sun引入泛型之时,Java已经进入第二个十年的开发,许多代码都使用原始类型编写,否则这些程序将会崩溃。

1
列表意味着这是一个未知类型的列表 - 因此在创建时你不会使用它(如你的示例),通常会将其用作方法参数。未绑定通配符只有在作为方法参数时才真正有用,例如:
public void printList(List<?> items)

这可以迭代任何未知项目的列表。在这种情况下,列表项可以达到相同的目的,但客户端可能会收到警告。
如果您有以下内容:
public void printList(List<Object> items)

只有 Object 的列表才能被处理 - 而不是字符串、整数等类型的列表。只能是对象。

看一下无界通配符 - 它解释得很好。


0

"undefined" List 包含类型为 Object 的列表,它是所有类型的父类,因此 List 不是类型安全的(可互相转换)

这就是为什么:

List undefinedlist = new ArrayList<TYPE>(); //IS LIST OF OBJECTS
undefinedList.add(new Integer(1)); //WORKS
undefinedList.add(new String("string")); //WORKS

好的..可以运行!


1
“Object”不是类型安全的?抱歉,我没明白这个。 - m0skit0
如果这是真的,那么(0)和(1)之间有什么区别? - joost
这两者之间的区别是一个是零,另一个是一吗?@joost - Aniket Inge
@Aniket,我的意思是在我提供的示例中。 - joost
1
List 不是“未定义”的,它是一个“原始类型”。 - Joachim Sauer

0
基本上,以下的?是什么意思。
List<?> wildcardList = new ArrayList<TYPE>();

意味着某种未知(特定)类型。因此,它不允许您向某种未知类型的列表中添加诸如StringInteger之类的内容,因为泛型旨在保证类型安全。

而在下面的例子中

List<Object> listOfObject = new ArrayList<TYPE>();

在Java中,你可以添加任何东西,因为一切都是Object。因此它是类型安全的。

还有以下内容:

List undefinedList = new ArrayList<TYPE>();

你告诉编译器你不想在那里使用泛型。这意味着你在undefinedList上调用的每个方法都将是非泛型的,因为你已经决定使用原始的List。集合框架中所有容器的非泛型版本都是为Object(Java中的任何对象)编写的。


谢谢。但我不了解原始和通用的区别是什么。 - joost
List<Object>(带有 < type-argument-here >)是泛型,而 List没有 < type-argument-here >)是原始类型。它们是在Java引入泛型之前编写的版本。 - Bhesh Gurung
这意味着它们是不同的类吗?因为如果没有提供类型参数,将使用哪种类型? - joost
有用的链接:https://dev59.com/r3M_5IYBdhLWcg3wgjW2https://dev59.com/oWs05IYBdhLWcg3wPfgR - joost

-1

List<?> 类型是泛型的:无论你在问号的位置上放置什么类型,都将在列表的方法中使用。因此,如果你创建了一个 List<String>,那么你可以执行 list.add(item),它只允许你放入一个 String。首先要保证类型安全。

List<String> list = new List<String>();
list.add("A");             // <-- Correct
list.add((Integer)10);     // <-- Error, it is a List of Strings

另一方面,List 允许放置任何 Object。因此,您可以创建一个 List,将 Giraffe 放入其中,稍后再放入一个 Squid。它不会关心,并且如果您期望仅有 Giraffe 对象在其中,它可能是编程错误的来源。
List list = new List();
list.add("A");             // <-- Allowed
list.add((Integer)10);     // <-- Also allowed,
                           // but now the list contains not only strings

这很清楚,但并不是我的问题的答案。 - joost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接