Wildcard (Java)
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.