I went through these topics
However, I still seem to be kind of lost with super
keyword:
When we declare a collection like that:
List<? super Number> list = null; list.add(new Integer(0)); // this compiles list.add(new Object()); // this doesn't compile
shouldn’t it be the opposite – we have a list that contains some objects (of unknown type) which are parents of Number
. So Object
should fit (since it is the parent of Number
), and Integer
shouldn’t. The opposite is the case for some reason.
Provided we have the following code
static void test(List<? super Number> param) { param.add(new Integer(2)); } public static void main(String[] args) { List<String> sList = new ArrayList<String>(); test(sList); // will never compile, however... }
It is impossible to compile the above code (and my sanity suggests that this is the right behaviour), but the basic logic could prove the opposite:
String is Object, Object is superclass of Number. So String should work.
I know this is crazy but isn’t this the reason why they didn’t allow <S super T>
constructs? If yes, then why <? super T>
is allowed?
Could someone help me restore the missing part of this logic chain?
Advertisement
Answer
The bounded wildcard in List<? super Number>
can capture Number
and any of its supertypes. Since Number extends Object implements Serializable
, this means that the only types that are currently capture-convertible by List<? super Number>
are:
List<Number>
List<Object>
List<Serializable>
Note that you can add(Integer.valueOf(0))
to any of the above types. however, you CAN’T add(new Object())
to a List<Number>
or a List<Serializable>
, since that violates the generic type safety rule.
Hence it is NOT true that you can add
any supertype of Number
to a List<? super Number>
; that’s simply not how bounded wildcard and capture conversion work. You don’t declare a List<? super Number>
because you may want to add an Object
to it (you can’t!); you do because you want to add Number
objects to it (i.e. it’s a “consumer” of Number
), and simply a List<Number>
is too restrictive.
References
- Angelika Langer’s Generics FAQs
- What is a bounded wildcard?
- When would I use a wildcard parameterized type with a lower bound? (“When a concrete parameterized type would be too restrictive.”)
- Why is there no lower bound for type parameters? (“Because it does not make sense.”)
- JLS 5.1.10 Capture Conversion
See also
- Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
- “PECS stands for producer-
extends
, consumer-super
- “PECS stands for producer-
Related questions
- Too many to list, PECS,
new Integer(0)
vsvalueOf
, etc