列表和列表之间的区别<! - ? - >

时间:2013-02-20 15:22:34

标签: java list generics wildcard unbounded-wildcard

我已经读过很多关于此的内容了,我知道:

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? 他们似乎是一样的&amp;给出相同的行为,给出(1)和(2)。

6 个答案:

答案 0 :(得分:2)

正如您自己发现的那样,

List undefinedListList<?> wildcardList并不相同。第一个是原始类型,第二个是无界通配符。

如果要使用泛型类型但是您不知道或不关心实际类型参数是什么,请使用无界通配符。你不能把任何东西(除了null)放到这个列表中,你所了解的元素就是它们扩展了Object(实际上List<?>List<? extends Object>相同)。无界通配符非常有用,因为如果您将天真地称为List<Object>,则无法为其分配List<String>,而您可以将List<String>分配给List<?>

你应该(几乎)从不需要使用原始类型,它们只能与Java 5之前编写的代码兼容。

答案 1 :(得分:1)

List意味着这是一个未知类型的列表 - 因此你不会在创建时使用它(如在你的例子中),你通常将它用作方法参数。未绑定的通配符仅在用作方法中的参数时才非常有用,例如:

public void printList(List<?> items)

这可以迭代(任何)未知项目的列表。在这种情况下,列表项目将达到相同的目的,但客户端可能会收到警告。

如果您有以下内容:

public void printList(List<Object> items)

然后只能处理Object列表 - 而不是列表字符串,整数等只有对象。

看看Unbounded Wildcards - 它很好地解释了

答案 2 :(得分:1)

List<?>被读作某种未知类型的列表。作为一个程序员,你不能假设它是什么类型,你不能把任何东西放到除null之外的这样的集合中。但您可以放心,您的列表是类型安全的,因为编译器将保证您的类型安全。

List基本上称为原始类型。也就是说它选择了编译器保证的类型安全性。因此,您可以将任何类型的元素放入该List中,从而破坏其不变量。不要再使用原始类型进行编码。它们基本上支持向后兼容性,因为java已经处于开发的第二个十年,当时Sun将泛型带到了表中,并且使用原始类型编写了大量代码,否则这些程序会破坏。

答案 3 :(得分:0)

“未定义”List包含类型Object的列表,它是所有类型的父类,因此List不是类型安全的(可互换的)

这就是为什么:

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

嗯..有效!

答案 4 :(得分:0)

List<?>类型是通用的:您在代码中使用的任何类型都将在列表的方法中使用。因此,您可以执行list.add(item),只有在创建String时才允许您加入List<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

答案 5 :(得分:0)

基本上,?位于以下

List<?> wildcardList = new ArrayList<TYPE>();

表示某种未知(特定)类型。因此,它不允许您将StringInteger之类的内容添加到某种未知类型的列表中,因为泛型是指类型安全的。

同时,在以下

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

你可以添加任何内容,因为Java中的所有内容都是Object。所以这是类型安全的。

还有以下

List undefinedList = new ArrayList<TYPE>();

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