?".
To specify a cage capable of holding some kind of animal:
Cage<? extends Animal> someCage = ...;Read "
? extends Animal" as "an unknown type that is a subtype of Animal,
possibly Animal itself", which boils down to "some kind of animal".
This is an example of a bounded wildcard, where Animal forms the upper bound of the expected type.
If you're asked for a cage that simply holds some kind of animal, you're free
to provide a lion cage or a butterfly cage.
Note: It's also possible to specify a lower bound by using thesuperkeyword instead ofextends. The code<? super Animal>, therefore, would be read as "an unknown type that is a supertype ofAnimal, possiblyAnimalitself". You can also specify an unknown type with an unbounded wildcard, which simply looks like<?>. An unbounded wildcard is essentially the same as saying<? extends Object>.
While
Cage<Lion> and Cage<Butterfly>
are not subtypes
of Cage<Animal>, they are in fact
subtypes of Cage<? extends Animal>:
someCage = lionCage; // OK someCage = butterflyCage; // OKSo now the question becomes, "Can you add butterflies and lions directly to
someCage?". As you can probably guess, the answer to this question is "no".
someCage.add(king); // compiler-time error someCage.add(monarch); // compiler-time errorIf
someCage is a butterfly cage, it would hold butterflies just fine, but
the lions would be able to break free. If it's a lion cage, then all would be well
with the lions, but the butterflies would fly away.
So if you can't put anything at all into someCage, is it
useless?
No, because you can still read its contents:
void feedAnimals(Cage<? extends Animal> someCage) {
for (Animal a : someCage)
a.feedMe();
}
Therefore, you could house your animals in their individual cages, as shown earlier,
and invoke this method first for the lions and then for the butterflies:
feedAnimals(lionCage); feedAnimals(butterflyCage);Or, you could choose to combine your animals in the all-animal cage instead:
feedAnimals(animalCage);