I have a very basic question.
The code below doesn\'t compile (assume Apple Extends Fruit):
List extends Fruit> numbers = new ArrayList&l
The best way to understand this is to think of the wildcard as saying something about the list, not the fruit. In other words:
List allBananas = getMyBananas();
enumerateMyFruit(allBananas);
static void enumerateMyFruit(List extends Fruit> myFruit) {
for (Fruit fruit : myFruit)
System.out.println(fruit);
}
When we pass allBananas to enumerateMyFruit, inside the method we lose information about the original declared type of the list. In this example we can very clearly see why we shouldn't be able to e.g. put apples in a List extends Fruit>, because we know that the list is actually a List. Again, the wildcard is telling us something about the declared type of the list.
List extends Fruit> should be read as something like "a list originally declared to hold Fruit or some subtype of Fruit, but we don't know what that declared type is anymore". All that we know is that everything we pull out of the list is a Fruit.
Also, you are right, we could iterate the list and use instanceof to find out what is really in the list, but this wouldn't tell us the original declared type of the list. In the above code snippet we would find out that everything in the list turned out to be a Banana, but I could have just as easily declared allBananas as a List.
You might also see why a ListList is not a List but it is a List extends Animal>. This comes with the restriction that we can't add to a List extends Animal>, because it might be a List, a List or something else. We don't know anymore.
There's also the ? super, which is the opposite. We can store Fruit in a List super Fruit> but we don't know what kinds of objects we will pull out of it. Its original declared type might actually be e.g. a List, with all kinds of other stuff in it.