java List<Object> 和 List<?> 有什么区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12340808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 08:29:20  来源:igfitidea点击:

What's the difference between List<Object> and List<?>

java

提问by Aldsjers Dostrnik

Before are all you burn me alive, I must say that I have googling this question many times and I still can't understand the difference between List<Object> and List<?>

在你把我活活烧死之前,我必须说我已经谷歌搜索了很多次这个问题,但我仍然无法理解 List<Object> 和 List<?> 之间的区别。

All books I've read say that in Java every class is implicitly a subclass of Object.

我读过的所有书籍都说,在 Java 中,每个类都隐含地是 Object 的子类

However I saw herethe follwing code:

但是我在这里看到了以下代码:

public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

This code is wrong (intentionally for educational purposes) and according to the author the reason is:

这段代码是错误的(故意用于教育目的),据作者说原因是:

[...] prints only a list of Object instances; it cannot print List<Integer>, List<String>, List<Double>, and so on, because they are not subtypes of List<Object>

[...] 只打印一个 Object 实例列表;它不能打印List<Integer>、List<String>、List<Double>等,因为它们不是 List<Object> 的子类型

The solution is:

解决办法是:

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}

As you can see, the only difference is the first line:

如您所见,唯一的区别是第一行:

public static void printList(List<Object> list) {
public static void printList(List<?> list) {

This is the reason of my question: What's the difference between List<Object> and List<?> ?

这就是我的问题的原因: List<Object> 和 List<?> 之间有什么区别?

After all is Objectsuperclass of everything or not?

毕竟Object是不是所有东西的超类?

If someone can help me with a simple explanation (I'm new with Java) I'll appreciate.

如果有人能帮我做一个简单的解释(我是 Java 新手),我将不胜感激。

Thank you in advance.

先感谢您。

采纳答案by Roberto Mereghetti

Explanation:

解释:

? is a "wildcard". You can use it in different ways:

? 是一个“通配符”。您可以通过不同方式使用它:

unbounded wildcard:

无界通配符:

? 

wildcard with upper bound:

带上限的通配符:

? extends Object (or another class)

wildcard with lower bound

带下限的通配符

? super Object (or another class)

Examples:

例子:

List <?> list;

you can assign to listany List with any type parameter.

您可以list使用任何类型参数分配给任何列表。

List<? extends Number> list;

you can assign to list any List with a type parameter Number (or Integer, Float, ecc)

您可以分配列出任何带有类型参数 Number(或 Integer、Float、ecc)的 List

List<? super Integer> list;

you can assign to list any List with a type parameter Integer, or a type in the type gerarchy of Integer(Number,Comparable, Serializable, Object ...)

您可以分配列出任何带有类型参数 Integer 的 List,或 Integer(Number,Comparable, Serializable, Object ...)

Summary:

概括:

So the declaration

所以声明

List<Object> list;

is similar to

类似于

List<? super Object> list;

because you can assign to "list" only a List of Objects; then you can use the list in this way:

因为您只能分配给“列表”一个对象列表;那么你可以这样使用列表:

    list = new ArrayList<Object>();
    list.add(new String(""));
    list.add(new Integer(3));

回答by meriton

That Stringis a subtype of Objectdoes not mean that List<String>is a subtype of List<Object>. If it were, the following code would compile:

String是 的子类型Object并不意味着List<String>是 的子类型List<Object>。如果是,下面的代码将编译:

List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
objects.add((Integer) 1);
strings.get(0).charAt(0); // but the Integer 1 does not have a charAt method ...

Therefore, List<String>is not a subtype of List<Object>.

因此,List<String>不是 的子类型List<Object>

Both List<String>and List<Object>are subtypes of List<?>. But because List<?>is the more general type, you can't know what type the add method takes:

这两个List<String>List<Object>的亚型List<?>。但是因为List<?>是更通用的类型,你无法知道 add 方法采用的是什么类型:

List<String> strings = new ArrayList<String>();
List<?> objects = strings;
objects.add((Integer) 1); // does not compile

回答by Johan Sj?berg

One of the major differences is how you can modify the lists. The following works well

主要区别之一是如何修改列表。以下效果很好

List<Object> l1;
l1.add(new Object()); // OK

while the second case produces a compilation error.

而第二种情况会产生编译错误。

List<?> l2;
l2.add(new Object()); // Compile error

The reasons for that I think has been debated a few times on the site already. In short,<?>means a(as in one) specificyet unknowntype. Since that type is not known compile-time, you're not allowed to modify the list.

我认为其原因已经在该网站上进行了几次辩论。总之,<?>意味着一个(如在一个特定未知类型。由于该类型在编译时未知,因此您不能修改列表。

回答by Dan D.

You can basically use both version in similar ways. However, there is one big difference. Let's declare the following:

您基本上可以以类似的方式使用这两个版本。但是,有一个很大的不同。让我们声明以下内容:

List<Object> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<String>();

Now, let's try the code below:

现在,让我们试试下面的代码:

list1.add("");// this works fine
list2.add("");// this one issues a compile error

Someone could ask why this. This is because in List<Object>, the code tells you that you have Objector subtypes there, but in List<?>you could have the same thing but you don't know exactly what. Someone could add Stringor Doubleand then try to read and cast to Integer. But again, it is not possible.

有人可能会问为什么会这样。这是因为在 中List<Object>,代码告诉您那里有Object或子类型,但在 中List<?>您可以拥有相同的东西,但您不知道究竟是什么。有人可以添加StringDouble,然后尝试读取并投射到Integer. 但同样,这是不可能的。

There may be other differences that I don't remember about now.

可能还有其他差异,我现在不记得了。

回答by TimK

Object is the superclass of String but List<Object> is not the superclass of List<String>. If it were, this would be a problem:

Object 是 String 的超类,但 List<Object> 不是 List<String> 的超类。如果是这样,这将是一个问题:

List<String> strings = ...
addObject(strings);
...
void addObjects(List<Object> objects) {
    objects.add(new Object());
}

Now strings contains an element that isn't a String.

现在字符串包含一个不是字符串的元素。

回答by davidmontoyago

This code is wrong (intentionally for educational purposes) and according to the author the reason is:

[...] prints only a list of Object instances; it cannot print List, List, List, and so on, because they are not subtypes of List

这段代码是错误的(故意用于教育目的),据作者说原因是:

[...] 只打印一个 Object 实例列表;它不能打印 List、List、List 等,因为它们不是 List 的子类型

This is because parameterized types are invariant, for instance for the classes X and Y, List<X>is neither a subtype nor a supertype of List<Y>.

这是因为参数化类型是不变的,例如对于类 X 和 Y,List<X>既不是 的子类型也不是超类型List<Y>

The difference resides in that the unbounded wildcard type?means that the type is unknown and you can′t assume anything about it. A List<?>is type safe, you can′t put any element other than nullin it and you can′t assume anything about the type of the object it contains.

不同之处在于无界通配符类型?意味着该类型是未知的,您无法对此进行任何假设。AList<?>是类型安全的,你不能在其中放置任何元素null,也不能假设它包含的对象的类型。

List<Object>obviously means that the List can contain objects of any type.

List<Object>显然意味着 List 可以包含任何类型的对象。

回答by viswarajramji

 public static void main(String args[]){

   List<? super Object> list=new ArrayList<>();
   list.add("A");//works

   List<Object> list1=new ArrayList<>();
   list1.add("B");//works

   List<?> list2=new ArrayList<>();
   list2.add("11");//compile time error;

   List<? extends Object> list4=new ArrayList<>();
   list4.add("123");//compile Time error
}

List< ? extend Object> & List< ? > doesn't allow to add anything follow this to know the reason :enter link description hereBut on the other hand List< ? super Object> allows to add values to List because the problem in the link provided doesn't exists .

列表< ? 扩展对象> & 列表< ? > 不允许在此之后添加任何内容以了解原因:在此处输入链接描述但另一方面 List< ? super Object> 允许向 List 添加值,因为提供的链接中的问题不存在。