36

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<?>

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

However I saw here the 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>

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<?> ?

After all is Object superclass of everything or not?

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

Thank you in advance.


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) specific yet unknown type. Since that type is not known compile-time, you're not allowed to modify the list.

4

7 回答 7

25

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 list any List with any type parameter.

List<? extends Number> list;

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

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 ...)

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));
于 2012-09-09T17:28:55.150 回答
9

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

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

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

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

我认为其原因已经在网站上讨论过几次了。简而言之,<?>意味着(如one特定未知类型。由于该类型在编译时是未知的,因此您不能修改列表。

于 2012-09-09T16:40:37.173 回答
8

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

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>.

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> strings = new ArrayList<String>();
List<?> objects = strings;
objects.add((Integer) 1); // does not compile
于 2012-09-09T16:46:20.497 回答
2

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 Object or subtypes there, but in List<?> you could have the same thing but you don't know exactly what. Someone could add String or Double and then try to read and cast to Integer. But again, it is not possible.

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

于 2012-09-09T16:43:26.767 回答
2

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

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

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

于 2012-09-09T16:51:03.977 回答
2

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

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>.

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 null in it and you can´t assume anything about the type of the object it contains.

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

于 2012-09-09T17:50:31.450 回答
0
 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. But on the other hand List< ? super Object> allows to add values to List because the problem in the link provided doesn't exists .

于 2017-08-01T17:10:39.933 回答