I was wondering why the following bit of code does not work:
Collection <? super String> col = new ArrayList<String>();
col.add(new Object());// does not compile
col.add("yo!");// compiles indeed;
If the type is <? super String>
it can contain anything which is super of String
(String included) not?
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 .
super is a lower bound, and extends is an upper bound.
The question mark (?) is known as the wildcard in generic programming. It represents an unknown type. The wildcard can be used in a variety of situations such as the type of a parameter, field, or local variable; sometimes as a return type.
Producer – If you want to only retrieve the elements from a generic collection, use extends . Consumer – If you want to only put elements into a generic collection, use super . If you do both retrieve and put operations with the same collection, you shouldn't use either extends or super .
Collection<? super String>
, counter to your intuition, does not mean "a collection which contains objects of type String
or its supertype". It means "col
will be a collection holding some definite type, which itself is String
or its supertype" (such as Object
, Serializable
, or CharSequence
).
The best way to think about Collection<? super String>
is that it is not a type, like you are used to in Java, but a pattern against which specific types are matched.
Now, the only thing you can safely add to any collection which matches the above pattern is a String
or its subclass (if there were any). Quite the opposite of what you would have expected, isn't it? That's Generics for you.
With a Collection <? super String>
, we don't know what kind of objects it contains exactly, but we know that it must be a collection of either String
or some superclass of String
, i.e. it is safe to put a String
into it but not necessarily an Object
. Conversely for methods that take things out of the collection (e.g. when iterating) we can't be sure we'll get strings back.
On the other hand with Collection<? extends Foo>
we know it's a collection of something that is either Foo
or some subclass of Foo
, so we can safely take something from the collection and know it will be assignable to Foo
, but we can't put anything in because we have no way of knowing what types would be safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With