Wildcard Types – Generics

Wildcard Types

Wildcard types are type parameters defined using the wildcard symbol ?. The wildcard ? by itself represents all types. The parameterized type List<?> represents a list of all types, whereas the concrete parameterized type List<Integer> only represents a list of Integer. In other words, a wildcard type can represent many types. Therefore, a parameterized type that has wildcard types as actual type parameters can represent a family of types, in contrast to a concrete parameterized type that only represents itself. The wildcard types provided in Java represent four subtype relationships that are summarized in Table 11.1.

Wildcard types provide the solution for increased expressive power to overcome the limitations discussed earlier when using generics in Java, but introduce limitations of their own as to what operations can be carried out on an object using references of wildcard types. We will use the class Node<E> in Example 11.2, p. 568, as a running example to discuss the use of wildcard types.

Table 11.1 Summary of Subtyping Relationships for Generic Types

NameSyntaxSemanticsDescription
Subtype covariance? extends TypeAny subtype of Type (including Type)Bounded wildcard with upper bound
Subtype contravariance? super TypeAny supertype of Type (including Type)Bounded wildcard with lower bound
Subtype bivariance?All typesUnbounded wildcard
Subtype invarianceTypeOnly type TypeType parameter/argument

Figure 11.3 Partial Type Hierarchy for Node<? extends Number>

The wildcard type ? extends Number denotes all subtypes of Number, and the parameterized type Node<? extends Number> denotes the family of invocations of Node<E> for types that are subtypes of Number. Figure 11.3 shows a partial type hierarchy for the parameterized type Node<? extends Number>. Note that the parameterized type Node<? extends Integer> is a subtype of the parameterized type Node<? extends Number>, since the wildcard type ? extends Integer represents all subtypes of Integer, and these are also subtypes of Number.

Click here to view code image

Node<? extends Integer> intSubNode = new Node<Integer>(100, null);
Node<? extends Number> numSupNode = intSubNode;

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Wildcard Types Wildcard types are type parameters defined using the wildcard symbol ?. The wildcard ? by itself represents all types. The parameterized type List<?> represents a list of all types, whereas the concrete parameterized type List<Integer> only represents a list of Integer. In other words, a wildcard type can represent many types. Therefore, a…

  • Parameterized Types A parameterized type (also called a type instance) is an invocation or instantiation of a generic type that is a specific usage of the generic type where the formal type parameters are replaced by actual type parameters. Analogy with method declarations and method invocations can be helpful in understanding the relationship between generic…

  • Declaration Order of Initializer Expressions When an object is created using the new operator, instance initializer expressions are executed in the order in which the instance fields are declared in the class. Java requires that the declaration of a field must occur before its usage in any initializer expression if the field is used on…

  • Upper Bounded Wildcard References: <? extends Type> The type of the reference s0 is Node<? extends Number>, where Type is Number. This means that the reference s0 refers to a node containing an object whose type is either Number or a subtype of Number, but the specific (sub)type of the object cannot always be determined…

  • Declaration Order of Static Initializers In the class ScheduleV1 below, the static field declaration at (1) has a forward reference to the static field numOfWeeks which has not been declared yet. The simple name of the static field numOfWeeks cannot be used in the initializer expression at (1) before its declaration. Click here to view…

  • Some Restrictions on Wildcard Types Wildcards cannot be used in instance creation expressions: Click here to view code image Node<?> anyNode = new Node<?>(2020, null);                 // Compile-time error!Node<? extends Integer> extIntNodeA               = new Node<? extends Integer>(0, null);     // Compile-time error!Node<? extends Integer> extIntNodeB = new Node<Integer>(0, null);  // OK The actual type parameter in the…

  • Lower Bounded Wildcard References: <? super Type> Using a reference of type Node<? super Number>, where Type is Number, we can only put a Number or a subtype object of Number into the node, as such a number would also be a subtype object of any supertype of Number. Since we cannot guarantee which specific…

  • Using Parameterized References to Call Set and Get Methods Generic classes are suitable for implementing ADTs called collections (also called containers) where the element type is usually specified by a type parameter. The Java Collections Framework is a prime example of such collections. A collection usually provides two basic operations: a set operation (also called…

  • 10.9 Constructing Initial Object State Object initialization involves constructing the initial state of an object when it is created by the new operator. First the fields are initialized to their default values (§3.4, p.103)—whether they are subsequently given non-default initial values or not—and then the constructor is invoked. This can lead to local chaining of…

  • 10.5 Initializers Initializers can be used to set initial values for fields in objects and classes. There are three kinds of initializers: Subsequent sections in this chapter provide details on these initializers, concluding with a discussion of the procedure involved in constructing the state of an object when the object is created using the new…