Download the JDK
Search the Tutorials
Hide the TOC
Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Wildcards

> Earlier we mentioned that English is ambiguous. The phrase "animal cage" can reasonably mean "all-animal cage", but it also suggests an entirely different concept: a cage designed not for any kind of animal, but rather for some kind of animal whose type is unknown. In generics, an unknown type is represented by the wildcard character "`?`".

> 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 the `super` keyword instead of `extends`. The code `<? super Animal>`, therefore, would be read as "an unknown type that is a supertype of `Animal`, possibly `Animal` itself". You can also specify an unknown type with an unbounded wilcard, 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; // OK

> So 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 error

> If `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);

« Previous • Trail • Next »
Previous page: Subtyping
Next page: Type Erasure