Generic Classes and Type Parameters

8.1.2 Generic Classes and Type Parameters

A class is generic if it declares one or more type variables (§4.4). These type variables are known as the type parameters of the class. The type

parameter section follows the class name and is delimited by angle brackets. TypeParameters:

< TypeParameterList > TypeParameterList:

TypeParameterList , TypeParameter TypeParameter

In a class's type parameter section, a type variable T directly depends on a type variable S if S is the bound of T , while T depends on S if either T directly depends on S or T directly depends on a type variable U that depends on S (using this definition recursively).

It is a compile-time error if a type variable in a class's type parameter section depends on itself.

The scope and shadowing of a class's type parameter is specified in §6.3 and §6.4.

Example 8.1.2-1. Mutually Recursive Type Variable Bounds

interface ConvertibleTo<T> { T convert(); } class ReprChange<T extends ConvertibleTo<S>,

S extends ConvertibleTo<T>> {

T t; void set(S s) { t = s.convert(); } S get() { return t.convert(); }

A generic class declaration defines a set of parameterized types (§4.5), one for each possible invocation of the type parameter section by type arguments. All of these parameterized types share the same class at run-time.

For instance, executing the code: Vector<String> x = new Vector<String>();

Vector<Integer> y = new Vector<Integer>(); boolean b = x.getClass() == y.getClass();

will result in the variable b holding the value true .

8.1.2 Generic Classes and Type Parameters CLASSES

It is a compile-time error if a generic class is a direct or indirect subclass of Throwable (§11.1.1).

This restriction is needed since the catch mechanism of the Java virtual machine works only with non-generic classes.

It is a compile-time error to refer to a type parameter of a generic class C anywhere in:

• the declaration of a static member of C (§8.3.1.1, §8.4.3.2, §8.5.1), or • the declaration of a static member of any type declaration nested within C , or

• a static initializer of C (§8.7), or

• a static initializer of any class declaration nested within C . Generic class declarations can be nested inside other declarations.

Example 8.1.2-2. Nested Generic Classes

class Seq<T> { T head; Seq<T> tail;

Seq() { this(null, null); } Seq(T head, Seq<T> tail) {

this.head = head; this.tail = tail;

} boolean isEmpty() { return tail == null; }

class Zipper<S> {

Seq<Pair<T,S>> zip(Seq<S> that) { if (isEmpty() || that.isEmpty()) { return new Seq<Pair<T,S>>(); } else { Seq<T>.Zipper<S> tailZipper = tail.new Zipper<S>(); return new Seq<Pair<T,S>>(

new Pair<T,S>(head, that.head), tailZipper.zip(that.tail));

} } class Pair<T, S> {

T fst; S snd; Pair(T f, S s) { fst = f; snd = s; }

} class Test {

public static void main(String[] args) {

CLASSES Inner Classes and Enclosing Instances 8.1.3

Seq<String> strs = new Seq<String>(

"a", new Seq<String>("b",

new Seq<String>()));

Seq<Number> nums = new Seq<Number>(

new Integer(1), new Seq<Number>(new Double(1.5),

new Seq<Number>()));

Seq<String>.Zipper<Number> zipper = strs.new Zipper<Number>();

Seq<Pair<String,Number>> combined = zipper.zip(nums); } }