Difference between <? super T> and <? extends T> in Java [duplicate]
Asked Answered
I

13

1052

What is the difference between List<? super T> and List<? extends T> ?

I used to use List<? extends T>, but it does not allow me to add elements to it list.add(e), whereas the List<? super T> does.

Inclusive answered 3/12, 2010 at 6:57 Comment(5)
Check out this excellent talk : youtu.be/V1vQf4qyMXg?t=22m24sIntertidal
here null we can addFleabag
A very good explanation with an example @ youtube.com/watch?v=34oiEq9nD0M&feature=youtu.be&t=1630 which explains <? super T> part but, gives an idea of another.Submersible
upper bounded: docs.oracle.com/javase/tutorial/java/generics/upperBounded.html lower bounded: docs.oracle.com/javase/tutorial/java/generics/lowerBounded.htmlWarila
I think of it like this: List<? extends B> means List whose elements have more than equal feature than B(all it's sub classes). List<? super B> means List whose elements have less than equal feature than B(all it's super classes).Holub
K
2060

extends

The wildcard declaration of List<? extends Number> foo3 means that any of these are legal assignments:

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number
  1. Reading - Given the above possible assignments, what type of object are you guaranteed to read from List foo3:

    • You can read a Number because any of the lists that could be assigned to foo3 contain a Number or a subclass of Number.
    • You can't read an Integer because foo3 could be pointing at a List<Double>.
    • You can't read a Double because foo3 could be pointing at a List<Integer>.
  2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

    • You can't add an Integer because foo3 could be pointing at a List<Double>.
    • You can't add a Double because foo3 could be pointing at a List<Integer>.
    • You can't add a Number because foo3 could be pointing at a List<Integer>.

You can't add any object to List<? extends T> because you can't guarantee what kind of List it is really pointing to, so you can't guarantee that the object is allowed in that List. The only "guarantee" is that you can only read from it and you'll get a T or subclass of T.

super

Now consider List <? super T>.

The wildcard declaration of List<? super Integer> foo3 means that any of these are legal assignments:

List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer
  1. Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from List foo3:

    • You aren't guaranteed an Integer because foo3 could be pointing at a List<Number> or List<Object>.
    • You aren't guaranteed a Number because foo3 could be pointing at a List<Object>.
    • The only guarantee is that you will get an instance of an Object or subclass of Object (but you don't know what subclass).
  2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

    • You can add an Integer because an Integer is allowed in any of above lists.
    • You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists.
    • You can't add a Double because foo3 could be pointing at an ArrayList<Integer>.
    • You can't add a Number because foo3 could be pointing at an ArrayList<Integer>.
    • You can't add an Object because foo3 could be pointing at an ArrayList<Integer>.

PECS

Remember PECS: "Producer Extends, Consumer Super".

  • "Producer Extends" - If you need a List to produce T values (you want to read Ts from the list), you need to declare it with ? extends T, e.g. List<? extends Integer>. But you cannot add to this list.

  • "Consumer Super" - If you need a List to consume T values (you want to write Ts into the list), you need to declare it with ? super T, e.g. List<? super Integer>. But there are no guarantees what type of object you may read from this list.

  • If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g. List<Integer>.

Example

Note this example from the Java Generics FAQ. Note how the source list src (the producing list) uses extends, and the destination list dest (the consuming list) uses super:

public class Collections { 
  public static <T> void copy(List<? super T> dest, List<? extends T> src) {
      for (int i = 0; i < src.size(); i++) 
        dest.set(i, src.get(i)); 
  } 
}

Also see How can I add to List<? extends Number> data structures?

Karttikeya answered 3/12, 2010 at 8:3 Comment(26)
I have a doubt here: If I need to add to a generic list and then get data from it, what should i do?Inclusive
@Inclusive - See the 3rd bullet under PECS above. You'll probably need to use a specific generic parameters (no wildcard, e.g. List<T>). Unfortunately, you can't have everything. You can either create a flexible reference to list by using a generic wildcard (e.g. <? super T> or <? extends T> and suffer limitations with respect to what you can add or read from it. Or else you can a less flexible reference to a list with a specific type (e.g. List<T>) and get better guarantees as to what you can read /write from it.Karttikeya
as an example you can see Collections copy method public static <T> void copy(List<? super T> dest, List<? extends T> src) { @ docjar.com/html/api/java/util/Collections.java.htmlHairston
@BertF: great explanation.one correction (if it ) do you mean to sayList<? super Integer> foo3 instead of List<? super Number> foo3 below super ?Piddling
I have reached this answer a couple of times. I whish I could vote more than once. Do you know that you are #1 in google search results?Connell
You can add an instance of a subclass of Integer this is wrong : Integer is a final classInterjection
Beautiful answer! I have 1 question though, you wrote 'You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists' - I thought you can only add a supertype of Integer because of <? super Integer>?Parturition
@Parturition - For the declaration List<? super X> foo, the <? super X> part of the declaration DOES NOT describe what you can add to the list - it describes what kinds of lists that the variable foo can point to. As an implication of all the different kinds of lists that foo can legally point to, only certain types of objects can be added to foo that is guaranteed to be acceptable to ANY type of list that foo may be pointed to.Karttikeya
@Parturition - Said another way: if List<? super VEGETABLES> foo is a special box that can contain a person with a special diet, i.e. a vegetarian who consumes only VEGETABLES and subclasses of VEGETABLES (i.e. List<VEGETABLES>) or that can contain a person with a "normal" diet -can eat vegetables, meat, dairy, or whatever (i.e. List<Object>), then what kind of food can I throw in the box that I'm sure that whoever is in the box will eat it? Only VEGETABLES or subclasses of VEGETABLES can be fed to the box foo since only they are edible to whichever person/List is really in the box.Karttikeya
@Bert F I still don't get it: if 'Only VEGETABLES or subclasses of VEGETABLES can be fed to the box foo', then what does '<? super VEGETABLES> mean?Parturition
@Bert F '<? super VEGETABLE>' does NOT describe what things you can add to 'foo' - it describes the kinds of Lists that 'foo' can point to. 'List<? super VEGETABLE> foo' means 'foo' is pointing at either List<VEGETABLE> or LIST<FOOD> at any given time, but you don't know which. Therefore you can only give 'foo' stuff that both would like. Both lists are okay to be given a VEGETABLE or subclass of VEGETABLE, but you can't give FOOD or MEAT (because List<VEGETABLE> can't eat FOOD or MEAT - has be a VEGETABLE).Karttikeya
For completness, List<? extends Number> foo3, In the writing part, you can actually write null, as in: foo3.add(null);Joeyjoffre
after reading your answer I had to try it out on my own. I did a simple class A{} class B extends A{} class C extends B{} and convinced myself that I had a totally wrong view about generics! :) Thank you so much!Cyst
Very good explanation! A tiny little note: "You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists." — correct, except that the Integer class is declared final and therefore cannot be extended.Wichita
What is the usage doing like this List<Number> can allow to do all operation what List<? super Number > can do and List<Number> can allow all operation what List<? extends Number > can doTopminnow
Can't figure out what would be wrong if instead of <? super T> in the copy method it is <T> i.e. ` class Test { static <T> void copy(List<T> dest, List<? extends T> src) { for (int i = 0; i < src.size(); i++) dest.set(i, src.get(i)); } public static void main(String[] args) { List<Integer> src = new ArrayList<>(Arrays.asList(1, 2)); List<Number> dest = new ArrayList<>(Arrays.asList(3, 4)); copy(dest, src); System.out.println(dest); } } `Junitajunius
Since Number is not widely used, it would be useful to add a comment about the relationship between Number, Integer and Double to complete this answer. (Integer and Double both extend Number.)Goober
I get no error when I execute the code: List<? extends Number> foo3 = new ArrayList<Integer>(); ((List<Double>) foo3).add(1.2); System.out.println(foo3.get(0)); That's to the point "You can't add a Double because foo3 could be pointing at a List<Integer>."Goodly
As mentioned by @Danon, a very nice explaination of genrics in Java 8 - nofluffjuststuff.com/magazine/2016/09/…Certification
@BertF it is valid to say in extends, on reading "You can read a Object (or something above Number) because any of the lists that could be assigned to foo3 contain a Number or a subclass of Number." maybe you could add that on the bulltetsDefiniens
Thanks, the last example explains everything! so, we "read" from "producer" and "write" to "consumer". I have no idea where these vague producer&consumer wording came from... Anyways I'll come back here in the future again.. :)Cheeks
This site elaborates in a concise way on this answer.Gd
@Bert F In the producer concept, why can not Java have a mechanism to check the instance type just before adding the element? Let's say, in the Number type collection, you need to add a Number type element Then, do a instance check on the collection type and accordingly add it. it might not be elegant, still, it looks like a possible solution. Thanks!!Bourse
@BertF If <? extends Foo> becomes <Foo>, then does <? super Foo> become <Object>?Aguedaaguero
I want to emphasize how important it is to really understand the difference between List<? extends T> (or List<? super T>) and List<T>. There's really nothing left that needs explaining; prior comments, as well as the OP, are both incredibly well-written. The point I'm trying to drive home is that if you don't immediately know the difference without thinking about it, it's probably an indicator that you should do more work with ALL types of generics until they are all second nature.Guayule
@BertF Can I double confirm my understanding with you on this PECS concept? ie PE: ? extends T meaning ? is a subclass of T and the you can read whatever T/? from the list, and CS: ? super T means that whatever ? is, it is a super class of T or T itself and because of this, you can only write T or whatever subclass of T to the listZins
D
339

Imagine having this hierarchy

enter image description here

1. Extends

By writing

    List<? extends C2> list;

you are saying that list will be able to reference an object of type (for example) ArrayList whose generic type is one of the 7 subtypes of C2 (C2 included):

  1. C2: new ArrayList<C2>();, (an object that can store C2 or subtypes) or
  2. D1: new ArrayList<D1>();, (an object that can store D1 or subtypes) or
  3. D2: new ArrayList<D2>();, (an object that can store D2 or subtypes) or...

and so on. Seven different cases:

    1) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E4
    2) new ArrayList<D1>(): can store    D1    E1 E2  
    3) new ArrayList<D2>(): can store       D2       E3 E4
    4) new ArrayList<E1>(): can store          E1             
    5) new ArrayList<E2>(): can store             E2             
    6) new ArrayList<E3>(): can store                E3             
    7) new ArrayList<E4>(): can store                   E4             

We have a set of "storable" types for each possible case: 7 (red) sets here graphically represented

enter image description here

As you can see, there is not a safe type that is common to every case:

  • you cannot list.add(new C2(){}); because it could be list = new ArrayList<D1>();
  • you cannot list.add(new D1(){}); because it could be list = new ArrayList<D2>();

and so on.

2. Super

By writing

    List<? super C2> list;

you are saying that list will be able to reference an object of type (for example) ArrayList whose generic type is one of the 7 supertypes of C2 (C2 included):

  • A1: new ArrayList<A1>();, (an object that can store A1 or subtypes) or
  • A2: new ArrayList<A2>();, (an object that can store A2 or subtypes) or
  • A3: new ArrayList<A3>();, (an object that can store A3 or subtypes) or...

and so on. Seven different cases:

    1) new ArrayList<A1>(): can store A1          B1 B2       C1 C2    D1 D2 E1 E2 E3 E4
    2) new ArrayList<A2>(): can store    A2          B2       C1 C2    D1 D2 E1 E2 E3 E4
    3) new ArrayList<A3>(): can store       A3          B3       C2 C3 D1 D2 E1 E2 E3 E4
    4) new ArrayList<A4>(): can store          A4       B3 B4    C2 C3 D1 D2 E1 E2 E3 E4
    5) new ArrayList<B2>(): can store                B2       C1 C2    D1 D2 E1 E2 E3 E4
    6) new ArrayList<B3>(): can store                   B3       C2 C3 D1 D2 E1 E2 E3 E4
    7) new ArrayList<C2>(): can store                            C2    D1 D2 E1 E2 E3 E4

We have a set of "storable" types for each possible case: 7 (red) sets here graphically represented

enter image description here

As you can see, here we have seven safe types that are common to every case: C2, D1, D2, E1, E2, E3, E4.

  • you can list.add(new C2(){}); because, regardless of the kind of List we're referencing, C2 is allowed
  • you can list.add(new D1(){}); because, regardless of the kind of List we're referencing, D1 is allowed

and so on. You probably noticed that these types correspond to the hierarchy starting from type C2.

Notes

Here the complete hierarchy if you wish to make some tests

interface A1{}
interface A2{}
interface A3{}
interface A4{}

interface B1 extends A1{}
interface B2 extends A1,A2{}
interface B3 extends A3,A4{}
interface B4 extends A4{}

interface C1 extends B2{}
interface C2 extends B2,B3{}
interface C3 extends B3{}

interface D1 extends C1,C2{}
interface D2 extends C2{}

interface E1 extends D1{}
interface E2 extends D1{}
interface E3 extends D2{}
interface E4 extends D2{}
Doloritas answered 20/10, 2015 at 21:16 Comment(7)
Looks like B1, B4, C1 and C3 should not be colored on the second picture. Because those are not included in the list above the picture.Pox
@Pox I'm not sure what you mean, those nodes are blue in the second picture, not being part of any set/caseDoloritas
@LuigiCortese Ok, you got me, I was wrong. What I wrote was about the last (third) picture not about the second picture. B1, B4, C1 and C3 should not be red on the last picture.Pox
Good post overall but I have to -1 because the last picture seems incorrect and I got no clarification about that.Pox
@Pox B1 is part of case 1, B4 is part of case 4, C1 is part of cases 1-2-5, C3 is part of cases 3-4-6. Is it possible that you're misinterpreting something?Doloritas
Let us continue this discussion in chat.Doloritas
I spent a bit of time confused by image 3 as well, but I think I figured it out and it makes sense: There are only 7 ArrayList<x> values, which are listed - B1 is not one of them, it will be a compiler error. But A1 is valid, and it can (in principle) hold both B1 and everything under B2, which is why B1 is in the same highlight as A1. The compiler will not let you list.add(new B1(){}); though (nor B2) because list could be e.g. a B3. You can only add C2 and sublasses because they work with all possible containers.Dufrene
C
162

I love the answer from @Bert F but this is the way my brain sees it.

I have an X in my hand. If I want to write my X into a List, that List needs to be either a List of X or a List of things that my X can be upcast to as I write them in i.e. any superclass of X...

List<? super   X>

If I get a List and I want to read an X out of that List, that better be a List of X or a List of things that can be upcast to X as I read them out, i.e. anything that extends X

List<? extends X>
Caterina answered 3/12, 2015 at 22:5 Comment(0)
F
49

I'd like to visualize the difference. Suppose we have:

class A { }
class B extends A { }
class C extends B { }

List<? extends T> - reading and assigning:

|-------------------------|-------------------|---------------------------------|
|         wildcard        |        get        |              assign             |
|-------------------------|-------------------|---------------------------------|
|    List<? extends C>    |    A    B    C    |                       List<C>   |
|-------------------------|-------------------|---------------------------------|
|    List<? extends B>    |    A    B         |             List<B>   List<C>   |
|-------------------------|-------------------|---------------------------------|
|    List<? extends A>    |    A              |   List<A>   List<B>   List<C>   |
|-------------------------|-------------------|---------------------------------|

List<? super T> - writing and assigning:

|-------------------------|-------------------|-------------------------------------------|
|         wildcard        |        add        |                   assign                  |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super C>     |              C    |  List<Object>  List<A>  List<B>  List<C>  |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super B>     |         B    C    |  List<Object>  List<A>  List<B>           |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super A>     |    A    B    C    |  List<Object>  List<A>                    |
|-------------------------|-------------------|-------------------------------------------|

In all of the cases:

  • you can always get Object from a list regardless of the wildcard.
  • you can always add null to a mutable list regardless of the wildcard.
Forsake answered 23/9, 2018 at 17:46 Comment(0)
P
34

Based on Bert F's answer I would like to explain my understanding.

Lets say we have 3 classes as

public class Fruit{}

public class Melon extends Fruit{}

public class WaterMelon extends Melon{}

Here We have

List<? extends Fruit> fruitExtendedList = …

//Says that I can be a list of any object as long as this object extends Fruit.

Ok now lets try to get some value from fruitExtendedList

Fruit fruit = fruitExtendedList.get(position)

//This is valid as it can only return Fruit or its subclass.

Again lets try

Melon melon = fruitExtendedList.get(position)

//This is not valid because fruitExtendedList can be a list of Fruit only, it may not be 
//list of Melon or WaterMelon and in java we cannot assign sub class object to 
//super class object reference without explicitly casting it.

Same is the case for

WaterMelon waterMelon = fruitExtendedList.get(position)

Now lets try to set some object in fruitExtendedList

Adding fruit object

fruitExtendedList.add(new Fruit())

//This in not valid because as we know fruitExtendedList can be a list of any 
//object as long as this object extends Fruit. So what if it was the list of  
//WaterMelon or Melon you cannot add Fruit to the list of WaterMelon or Melon.

Adding Melon object

fruitExtendedList.add(new Melon())

//This would be valid if fruitExtendedList was the list of Fruit but it may 
//not be, as it can also be the list of WaterMelon object. So, we see an invalid 
//condition already.

Finally let try to add WaterMelon object

fruitExtendedList.add(new WaterMelon())

//Ok, we got it now we can finally write to fruitExtendedList as WaterMelon 
//can be added to the list of Fruit or Melon as any superclass reference can point 
//to its subclass object.

But wait what if someone decides to make a new type of Lemon lets say for arguments sake SaltyLemon as

public class SaltyLemon extends Lemon{}

Now fruitExtendedList can be list of Fruit, Melon, WaterMelon or SaltyLemon.

So, our statement

fruitExtendedList.add(new WaterMelon())

is not valid either.

Basically we can say that we cannot write anything to a fruitExtendedList.

This sums up List<? extends Fruit>

Now lets see

List<? super Melon> melonSuperList= …

//Says that I can be a list of anything as long as its object has super class of Melon.

Now lets try to get some value from melonSuperList

Fruit fruit = melonSuperList.get(position)

//This is not valid as melonSuperList can be a list of Object as in java all 
//the object extends from Object class. So, Object can be super class of Melon and 
//melonSuperList can be a list of Object type

Similarly Melon, WaterMelon or any other object cannot be read.

But note that we can read Object type instances

Object myObject = melonSuperList.get(position)

//This is valid because Object cannot have any super class and above statement 
//can return only Fruit, Melon, WaterMelon or Object they all can be referenced by
//Object type reference.

Now, lets try to set some value from melonSuperList.

Adding Object type object

melonSuperList.add(new Object())

//This is not valid as melonSuperList can be a list of Fruit or Melon.
//Note that Melon itself can be considered as super class of Melon.

Adding Fruit type object

melonSuperList.add(new Fruit())

//This is also not valid as melonSuperList can be list of Melon

Adding Melon type object

melonSuperList.add(new Melon())

//This is valid because melonSuperList can be list of Object, Fruit or Melon and in 
//this entire list we can add Melon type object.

Adding WaterMelon type object

melonSuperList.add(new WaterMelon())

//This is also valid because of same reason as adding Melon

To sum it up we can add Melon or its subclass in melonSuperList and read only Object type object.

Penumbra answered 19/3, 2016 at 8:8 Comment(1)
Thanks, this is great, Its the closest I have got to understanding contravariance, I understand Covariance, We see this example being shown a lot: <? super T>, Why can't we instead just reference T ? Or why not Object ? The only reason I can think off is we don't want some sibling class to be put in, but I don't understand why we need contravariance ? If we have <? extends T> as producer, can't the consumer be just T ? Since its always going to consunme some T or subclass of T ? Or why can't the consumer just have Object instead of super ?Chemiluminescence
P
21

super is a lower bound, and extends is an upper bound.

According to http://download.oracle.com/javase/tutorial/extra/generics/morefun.html :

The solution is to use a form of bounded wildcard we haven't seen yet: wildcards with a lower bound. The syntax ? super T denotes an unknown type that is a supertype of T (or T itself; remember that the supertype relation is reflexive). It is the dual of the bounded wildcards we've been using, where we use ? extends T to denote an unknown type that is a subtype of T.

Psychopath answered 3/12, 2010 at 7:4 Comment(0)
S
14

Adding an item to the list:

  • List< ? extends X > doesn't allow to add anything, except for null into the list.

  • List< ? super X > allows to add anything that is-a X (X or its subtype), or null.

Getting an item from the list:

  • When you get an item from List< ? extends X >, you can assign it to a variable of type X or any supertype of X, including Object.
  • When you get an item from List< ? super X >, you can only assign it to a variable of type Object.

Some examples:

    List<? extends Number> list1 = new ArrayList<Integer>();
    list1.add(null);  //OK
    Number n = list1.get(0);  //OK
    Serializable s = list1.get(0);  //OK
    Object o = list1.get(0);  //OK

    list1.add(2.3);  //ERROR
    list1.add(5);  //ERROR
    list1.add(new Object());  //ERROR
    Integer i = list1.get(0);  //ERROR

    List<? super Number> list2 = new ArrayList<Number>();
    list2.add(null);  //OK
    list2.add(2.3);  //OK
    list2.add(5);  //OK
    Object o = list2.get(0);  //OK

    list2.add(new Object());  //ERROR
    Number n = list2.get(0);  //ERROR
    Serializable s = list2.get(0);  //ERROR
    Integer i = list2.get(0);  //ERROR
Schwitzer answered 28/9, 2017 at 12:44 Comment(0)
S
6

The up voted answers covers the details on many aspects. However, I would try to answer this in different way.

There are 2 things we need to consider,

1. Assignment to the list variable

List<? extends X> listvar;

Here, any list of X or list of subclasses of X can be assigned to listvar.

List<? extends Number> listvar; listvar = new ArrayList<Number>(); listvar = new ArrayList<Integer>();


List<? super X> listvar;

Here, any list of X or list of superclasses of X can be assigned to listvar.

List<? super Number> listvar; listvar = new ArrayList<Number>(); listvar = new ArrayList<Object>();

2. Perform Read or Write operation on the list variable

`List<? extends X> listvar;`

You can use this feature to accept a list in method arguments and perform any operations on type X (Note: You can only read objects of type X from the list).

`List<? super Number> listvar;

You can use this feature to accept a list in method arguments and perform any operations on type Object as You can only read objects of type Object from the list. But yes, additional thing here is , you can add objects of type X into the list.

Subak answered 31/3, 2018 at 4:20 Comment(0)
B
5

Using extends you can only get from the collection. You cannot put into it. Also, though super allows to both get and put, the return type during get is ? super T.

Bourn answered 28/1, 2014 at 6:51 Comment(0)
L
5

You can go through all the answers above to understand why the .add() is restricted to '<?>', '<? extends>', and partly to '<? super>'.

But here's the conclusion of it all if you want to remember it, and dont want to go exploring the answer every time:

List<? extends A> means this will accept any List of A and subclass of A. But you cannot add anything to this list. Not even objects of type A.

List<? super A> means this will accept any list of A and superclass of A. You can add objects of type A and its subclasses.

Liftoff answered 22/8, 2017 at 21:5 Comment(1)
Thanks, but the contravariance <? super A> confuses me, why do we need this ? Why can't we just type hint A instead of <? super A> ? Or why can't we just put Object instead of <? super A> ? I understand the what, but I want to know the why please,Chemiluminescence
S
4

The most confusing thing here is that whatever type restrictions we specify, assignment works only one way:

baseClassInstance = derivedClassInstance;

You may think that Integer extends Number and that an Integer would do as a <? extends Number>, but the compiler will tell you that <? extends Number> cannot be converted to Integer (that is, in human parlance, it is wrong that anything that extends number can be converted to Integer):

class Holder<T> {
    T v;
    T get() { return v; }
    void set(T n) { v=n; }
}
class A {
    public static void main(String[]args) {
        Holder<? extends Number> he = new Holder();
        Holder<? super Number> hs = new Holder();

        Integer i;
        Number n;
        Object o;

        // Producer Super: always gives an error except
        //       when consumer expects just Object
        i = hs.get(); // <? super Number> cannot be converted to Integer
        n = hs.get(); // <? super Number> cannot be converted to Number
                      // <? super Number> cannot be converted to ... (but
                      //       there is no class between Number and Object)
        o = hs.get();

        // Consumer Super
        hs.set(i);
        hs.set(n);
        hs.set(o); // Object cannot be converted to <? super Number>

        // Producer Extends
        i = he.get(); // <? extends Number> cannot be converted to Integer
        n = he.get();
        o = he.get();

        // Consumer Extends: always gives an error
        he.set(i); // Integer cannot be converted to <? extends Number>
        he.set(n); // Number cannot be converted to <? extends Number>
        he.set(o); // Object cannot be converted to <? extends Number>
    }
}

hs.set(i); is ok because Integer can be converted to any superclass of Number (and not because Integer is a superclass of Number, which is not true).

EDIT added a comment about Consumer Extends and Producer Super -- they are not meaningful because they specify, correspondingly, nothing and just Object. You are advised to remember PECS because CEPS is never useful.

Shrewsbury answered 8/7, 2016 at 15:11 Comment(0)
V
2

Example, Order of inheritance is assumed as O > S > T > U > V

Using extends Keyword ,

Correct:

List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();

InCorrect:

List<? extends T> Object = new List<S>();
List<? extends T> Object = new List<O>();

super Keyword:

Correct:

List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();

InCorrect:

List<? super T> Object = new List<U>();
List<? super T> Object = new List<V>();

Adding object: List Object = new List();

Object.add(new T()); //error

But Why error ? Let's look at the Possibilities of initializations of List Object

List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();

If we use Object.add(new T()); then it will be correct only if

List<? extends T> Object = new List<T>(); 

But there are extra two possibilities

List Object = new List(); List Object = new List(); If we try to add (new T()) to the above two possibilities it will give an error because T is the superior class of U and V . we try to add a T object [which is (new T()) ] to List of type U and V . Higher class object(Base class) cannot be passed to lower class Object(Sub class).

Due to the extra two possibilities , Java gives you error even if you use the correct possilibity as Java don't know what Object you are referring to .So you can't add objects to List Object = new List(); as there are possibilities that are not valid.

Adding object: List Object = new List();

Object.add(new T()); // compiles fine without error
Object.add(new U()); // compiles fine without error
Object.add(new V()); // compiles fine without error

Object.add(new S()); //  error
Object.add(new O()); //  error

But why error occurs in the above two ? we can use Object.add(new T()); only on the below possibilities,

List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();

If we Tried to use Object.add(new T()) in List Object = new List(); and List Object = new List(); then it will give error This is because We can't add T object[which is new T()] to the List Object = new List(); because it is an object of type U . We can't add a T object[which is new T()] to U Object because T is a base class and U is a sub class . We can't add base class to subclass and that's why error occurs . This is same for the another case .

Vaticide answered 22/7, 2018 at 17:57 Comment(1)
not sure why this was downvoted... other than for the naming of variables in a .net fashion. I corrected the -1, but you probably should conform to the normal naming convention :) oracle.com/technetwork/java/codeconventions-135099.htmlRobertson
C
1

The generic wildcards target two primary needs:

Reading from a generic collection Inserting into a generic collection There are three ways to define a collection (variable) using generic wildcards. These are:

List<?>           listUknown = new ArrayList<A>();
List<? extends A> listUknown = new ArrayList<A>();
List<? super   A> listUknown = new ArrayList<A>();

List<?> means a list typed to an unknown type. This could be a List<A>, a List<B>, a List<String> etc.

List<? extends A> means a List of objects that are instances of the class A, or subclasses of A (e.g. B and C). List<? super A> means that the list is typed to either the A class, or a superclass of A.

Read more : http://tutorials.jenkov.com/java-generics/wildcards.html

Chor answered 23/8, 2015 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.