This following is from generics tutorials:
Say class R extends S,
public void addR(List<? extends S> s) {
s.add(0, new R()); // Compile-time error!
}
You should be able to figure out why the code above is disallowed. The type of the second parameter to s.add() is ? extends S -- an unknown subtype of S. Since we don't know what type it is, we don't know if it is a supertype of R; it might or might not be such a supertype, so it isn't safe to pass a R there.
I have read it a few times but still I don't quite understand why the following is an error
Given the List.add()'s signature
void add(int index, E element)
isn't it equivalent to
void add(int index, <? extends S> element) // just to explain the idea, not a valid syntax
why is it an error call add(0, new R()) R being an S?
Figured this would be the simplest explanation
Class structure:
Code usage:
in this case the following would be invalid:
Here's what the text in italics is referring to:
The parameter
s
, of typeList<? extends S>
, could be not just an instance ofList<S>
orList<R>
, but alsoList<T>
whereT
extendsS
. In that case, even ifR
also extendsS
,R
does not necessarily extendT
(they could be, e.g. siblings in the class hierarchy). Since you can only put a value of typeT
in such a collection, the compiler can't guarantee at compile time that putting anR
there would be safe.To give a more concrete example, you can't add a
Double
to aList<? extends Number>
, even thoughDouble
extendsNumber
! That's because a variable of typeList<? extends Number>
could, for example, be assigned aList<Integer>
at runtime, and adding aDouble
to such a list is not allowed.In fact, you can't actually call the
add
method of a list declared to beList<? extends S>
, because at runtime the wildcard could always represent some subtype ofS
that isn't a superclass of the thing you want to add. You can however read from such a list, since it's guaranteed that the wildcard is a subtype ofS
, and therefore can be assigned to a variable of typeS
:This general idea is referred to as PECS (producer-extends, consumer-super). Chapter 5 of Effective Java (conveniently enough, it's the sample chapter you can download from the book's website) has more to say about this and other subtleties of generics.