Jump to content

Wildcard (Java)

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Solymosi7 (talk | contribs) at 11:36, 23 February 2011 (Created page with 'The wildcard <code>?</code> in Java is a special actual parameter for the instantiation of generic (parameterized) types. It can be used for the instantiation, not ...'). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

The wildcard ? in Java is a special actual parameter for the instantiation of generic (parameterized) types. It can be used for the instantiation, not in the definition of a generic unit. This article summarizes the most important rules for its use.

Covariance for generic types

Unlike arrays (which are covariant in Java) different instantiations of a generic type are not compatible to each other, not even explicitly: With the declaration Generic<Supertype> superGeneric; Generic<Subtype> subGeneric; the compiler would report a conversion error for both castings (Generic<Subtype>)superGeneric and (Generic<Supertype>)subGeneric.

This incompatibility may be softened up by the wildcard if ? is used as actual type parameter: Generic<?> is the abstract supertype for all instantiations of the generic type. It means, no objects of this type may be created, only variables. The usage of such a variable is to refer to instantiations of Generic with any actual type parameter.

Wildcard as Parameter Type

In the body of a generic unit, the (formal) type parameter is handled like its upper bound (expressed with extends; Object if not constrained). If the return type of a function is the type parameter, the result (e.g. of type ?) can be referenced by a variable of the type of the upper bound (or Object). In the other direction, the wildcard fits to no other type, not even to Object: If ? has been applied for the formal parameter of a method, no actual parameters can passed to it. It can be called only by casting of the wildcard reference:

<program language="Java"> class Generic <T extends UpperBound> { private T t; void write(T t) { this.t = t; } T read() { return t; } } ... Generic<?> wildcardReference; UpperBond ub = wildcardReference.read(); // Object would also be OK wildcardReference.write(new Object()); // type error ((Generic<UpperBound>)wildcardReference).write(new UpperBound()); // OK </program>

Wildcard Constrains

Not only the formal type parameters in the generic unit, also the wildcard can be (further) constrained if one doesn’t want to be compatible to all instantiations:

Generic<? extends SubtypeOfUpperBound> referenceConstrainedFromAbove;

This reference can hold any instantiation of Generic with an actual type parameter of SubtypeOfUpperBound’s subtype. A constraint with a lower bound

Generic<? super SubtypeOfUpperBound> referenceConstrainedFromBelow;

can hold instantiations of Generic with any supertype (e.g. UpperBound) of SubtypeOfUpperBound. Thus it is possible to constrain a reference’s compatibility from both sides: from above by the generic class definition (extends UpperBound), from below by the reference declaration (super SubtypeOfUpperBound).

Object Creation with Wildcard

Although no objects may be created with a wildcard type (new Generic<?>() is forbidden because Generic<?> is abstract), an array object may be created only by an unconstrained wildcard instantiation (and by no other instantiations): new Generic<?>[20] is correct, while new Generic<UpperBound>[20] is prohibited.

An example of using wildcard in List's instantiation is contained in the article Generics.