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)

我明白为什么你不能向通配符列表添加任何东西,因为它的类型可以是任何东西。但是,为什么可以添加到 undefinedList 中?给定(1)和(2),它们看起来相同并表现出相同的行为。

4

6 回答 6

4

List undefinedListList<?> wildcardList你自己发现的不一样。第一个是原始类型,第二个是无界通配符。

如果您想使用泛型类型但不知道或不关心实际类型参数是什么,请使用无界通配符。你不能把任何东西(除了null)放到这个列表中,你所知道的关于你从中得到的元素是它们扩展了 Object (实际上List<?>与 相同List<? extends Object>)。无界通配符很有用,因为如果您天真地将某些内容声明为List<Object>,则无法将例如分配List<String>给它,而可以将 a 分配List<String>给 aList<?>

您应该(几乎)永远不需要使用原始类型,它们仅用于与 Java 5 之前编写的代码兼容。

于 2013-02-20T15:34:04.780 回答
2

List<?>被读取为一些未知类型的列表。作为程序员,您不能对它是什么类型做出任何假设,并且除了 null 之外,您不能将任何东西放入这样的集合中。但是您可以放心,您的列表是类型安全的,因为编译器会为您保证类型安全。

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

于 2013-02-20T18:20:33.347 回答
1

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

public void printList(List<?> items)

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

如果您有以下情况:

public void printList(List<Object> items)

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

看看无界通配符- 它很好地解释了它

于 2013-02-20T15:42:06.700 回答
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

好吧..工作!

于 2013-02-20T15:25:28.643 回答
0

基本上,?在以下

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

表示某种未知(特定)类型。因此,它不允许您添加类似String, 或Integer某些未知类型的列表,因为泛型是类型安全的。

同时,在下面

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

您可以向其中添加任何内容,因为一切都是ObjectJava 中的。所以它是类型安全的。

还有以下

List undefinedList = new ArrayList<TYPE>();

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

于 2013-02-20T15:32:57.503 回答
-1

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
于 2013-02-20T15:27:19.223 回答