5

Is there a difference between these two Lists?

List<Something> a;
List<? extends Something> b;

I know that for example

List<Object> a;
List<?> b;
List c;

and

List<Something> a;
List<? extends SomeInterfaceSomethingImplements> b;

are all different, but how about these? And is it different if Something was replaced with Object?

List<Object> a;
List<? extends Object> b;
PurkkaKoodari
  • 6,703
  • 6
  • 37
  • 58
  • See: http://stackoverflow.com/questions/897935/when-do-java-generics-require-extends-t-instead-of-t-and-is-there-any-down – Diego Basch Sep 21 '13 at 17:56
  • Makind the type of a field `List` only allows you to assign a `List` to it. A `List` is not considered a `List` due to type erasure. A reference declared as `List extends Object>` can be assigned a list of elements belonging to an arbitrary subclasss of `Object` (which holds true for all classes in Java). This could mean `List`, `List`, `List` – toniedzwiedz Sep 21 '13 at 17:57
  • @Tom Right, except that I'm pretty sure it's not because of type erasure. `String` and `Object` are already there, they are just checked, it has nothing to do with erasing types. – Bernhard Barker Sep 21 '13 at 18:02
  • I don't see how this is a duplicate. In the other question the asker is comparing `` and ` extends Serializable>`. In my case it would be for example `` and ` extends Date>`. – PurkkaKoodari Sep 22 '13 at 08:33

4 Answers4

11

List<Something> is a list of objects of type Something. List<? extends Something> is a list of objects of some particular type which extends Something.

So, List<Object> can have objects of any class that extends Object. But List<? extends Object> can only be initialised to or assigned as a List of a objects of a particular class that extends Object

When is this useful? Say you want to write a method that takes a List of Objects and prints each item:

void print(List<Object> list) {
    for (Object obj: list) {
        System.out.println(obj)
    }
}

Now, let's say you have a List<Integer>. You cannot pass it to the above method, because print takes List<Object>, and List<Integer> cannot be assigned to a List<Object>. To get around this, we redefine print as:

void print2(List<? extends Object> list) {
    for (Object obj: list) {
        System.out.println(obj)
    }
}

Now, we can pass List of any subclass of Object to print2. print2 will accept List<Integer>, List<String> etc.

On the flip side, you cannot add anything to the list inside print2, because print2 does not know the concrete subtype of Object which is used. Hence you can use ? extends ... only in methods where you do not have to add anything to the List.

Hari Menon
  • 33,649
  • 14
  • 85
  • 108
  • `List extends Object>` could also be initialized to `List`. – Ryan Sep 21 '13 at 18:13
  • @Ryan, yes it can be. The usefulness of `?` lies in the fact that it can be assigned to `List` as well, whereas you cannot assign a `List` to a `List` – Hari Menon Sep 21 '13 at 18:17
  • The wording of the 2nd sentence of the 2nd paragraph sounds like it can't be. – Ryan Sep 21 '13 at 18:23
2

As others have mentioned, List<Something> is a list of objects of type Something, whereas List<? extends Something> would be initialized to be a list of a different object type, as long as the object type extends Something.

List<Object> would be a list of objects of type Object.

List<? extends Object> could initialized to be a list of any data types that extend Object.

Here is some code showing what happens when using Object compared to ? extends Object:

import java.util.ArrayList;

public class test {
    class A {}

    public static void main(String[] args) {
        // No error
        ArrayList<Object> arrObj = new ArrayList<Object>();

        // Error
        ArrayList<Object> arrObj2 = new ArrayList<A>();

        // No Error
        ArrayList<? extends Object> arrExt = new ArrayList<Object>();

        // No Error
        ArrayList<? extends Object> arrExt2 = new ArrayList<A>();
    }

}
Ryan
  • 712
  • 7
  • 21
1

List<Something> means the implementation should be something like ArrayList<Something>. But the other case List<? extends Something> means implementation can be anything like ArrayList<Something> or ArrayList<SomethingChild> where SomethingChild extends Something.

You can assign

List<? extends Something> list = new ArrayList<SomethingChild>();

whereas you cannot assign

List<Something> list = new ArrayList<SomethingChild>();

which will result in compilation error.

You can learn more about Generics and wildcards used in Generics for getting some perspicacity

prasanth
  • 3,502
  • 4
  • 28
  • 42
0

First one is collection of object type something and the second one is collection of objects that are subtype of something.

Sumit
  • 1
  • 1