What is the difference between <? super E>
and <? extends E>
?
For instance when you take a look at class java.util.concurrent.LinkedBlockingQueue
there is the following signature for the constructor:
public LinkedBlockingQueue(Collection<? extends E> c)
and for one for the method:
public int drainTo(Collection<? super E> c)
Before the answer; Please be clear that
Example:
Hope this will help you to understand wildcard more clear.
<? super E>
meansany object including E that is parent of E
<? extends E>
meansany object including E that is child of E .
The first says that it's "some type which is an ancestor of E"; the second says that it's "some type which is a subclass of E". (In both cases E itself is okay.)
So the constructor uses the
? extends E
form so it guarantees that when it fetches values from the collection, they will all be E or some subclass (i.e. it's compatible). ThedrainTo
method is trying to put values into the collection, so the collection has to have an element type ofE
or a superclass.As an example, suppose you have a class hierarchy like this:
and a
LinkedBlockingQueue<Parent>
. You can construct this passing in aList<Child>
which will copy all the elements safely, because everyChild
is a parent. You couldn't pass in aList<Object>
because some elements might not be compatible withParent
.Likewise you can drain that queue into a
List<Object>
because everyParent
is anObject
... but you couldn't drain it into aList<Child>
because theList<Child>
expects all its elements to be compatible withChild
.A wildcard with an upper bound looks like " ? extends Type " and stands for the family of all types that are subtypes of Type , type Type being included. Type is called the upper bound .
A wildcard with a lower bound looks like " ? super Type " and stands for the family of all types that are supertypes of Type , type Type being included. Type is called the lower bound .
You have a Parent class and a Child class inherited from Parent class.The Parent Class is inherited from another class called GrandParent Class.So Order of inheritence is GrandParent > Parent > Child. Now, < ? extends Parent > - This accepts Parent class or either Child class < ? super Parent > - This accepts Parent class or either GrandParent class
You might want to google for the terms contravariance (
<? super E>
) and covariance (<? extends E>
). I found that the most useful thing when comprehending generics was for me to understand the method signature ofCollection.addAll
:Just as you'd want to be able to add a
String
to aList<Object>
:You should also be able to add a
List<String>
(or any collection ofString
s) via theaddAll
method:However you should realize that a
List<Object>
and aList<String>
are not equivalent and nor is the latter a subclass of the former. What is needed is the concept of a covariant type parameter - i.e. the<? extends T>
bit.Once you have this, it's simple to think of scenarios where you want contravariance also (check the
Comparable
interface).