Page 172 from OCP guide, chapter 3 Generics and Collections, states:
The problem stems from the fact that Java doesn’t know what type List<? extends
Bird> really is. It could be List<Bird> or List<Sparrow> or some other generic type that
hasn’t even been written yet. Line 7 doesn’t compile because we can’t add a Sparrow to
List<Bird>, and line 8 doesn’t compile because we can’t add a Bird to List<Sparrow>.
From Java’s point of view, both scenarios are equally possible so neither is allowed.
I didn't get the point, why that 2 lines does not compiles, cause from my point of view,
Sparrow extends Bird, and a list of Type Bird must accept a Bird.
Thiago Medeiros wrote:... a list of Type Bird must accept a Bird.
Any help will be welcome.
The problem is, the compiler doesn't know that it has a List of Birds. The declaration of the variable "birds" says it's a List<? extends Bird>. As far as the compiler is concerned, it might be a List<Bird> or a List<Sparrow> or a List<RedFoxSparrow> or something else - it has no idea. When later code tries to add a Sparrow or Bird, the compiler can't guarantee that the List will accept that, because the List might be a type that can't accept Sparrow or Bird.
Generally, if you have a List<? extends Foo> you can take things out of it, and the compiler will know that those things are some type of Foo. But you can't put things in to the list, because the compiler can't know what the ? in List<? extends Foo> actually represents. It could be something more specialized than the type you're trying to add.
Suppose you have a class 'OneWingedSparrow extends Sparrow'. Then it is possible that you have a List<OneWingedSparrow>, and it makes sense that it is NOT allowed to add a normal Sparrow to that list. As far as the compiler concerns, List<? extends Bird> might be that OneWingedSparrow List.
For the same reason you cannot add a Bird to that list.
What about the other way? Can you add a OnrWingedSparrow to a List<Bird>?