Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
java_language_specification_7.pdf
Скачиваний:
13
Добавлен:
21.03.2016
Размер:
3.11 Mб
Скачать

4.5

Parameterized Types

TYPES, VALUES, AND VARIABLES

If C had been declared in a different package than T, then the call to mCDefault would give rise to a compile-time error, as that member would not be accessible at the point where T is declared.

4.5 Parameterized Types

A generic class or interface declaration C (§8.1.2, §9.1.2) with one or more type parameters A1,...,An which have corresponding bounds B1,...,Bn defines a set of parameterized types, one for each possible invocation of the type parameter section.

Each parameterized type in the set is of the form C<T1,...,Tn> where each type argument Ti ranges over all types that are subtypes of all types listed in the corresponding bound. That is, for each bound type Si in Bi, Ti is a subtype of

Si[F1:=T1,...,Fn:=Tn].

A parameterized type is written as a ClassType or InterfaceType that contains at least one type declaration specifier immediately followed by a type argument list <T1,...,Tn>. The type argument list denotes a particular invocation of the type parameters of the generic type indicated by the type declaration specifier.

Given a type declaration specifier immediately followed by a type argument list, let C be the final Identifier in the specifier.

It is a compile-time error if C is not the name of a generic class or interface, or if the number of type arguments in the type argument list differs from the number of type parameters of C.

Let P = C<T1,...,Tn> be a parameterized type. It must be the case that, after P is subjected to capture conversion (§5.1.10) resulting in the type C<X1,...,Xn>, for each type argument Xi (1 i n), Xi <: Bi[A1:=X1,...,An:=Xn] (§4.10), or a compiletime error occurs.

The notation [Ai:=Ti] denotes substitution of the type variable Ai with the type Ti for 1 i n, and is used throughout this specification.

In this specification, whenever we speak of a class or interface type, we include the generic version as well, unless explicitly excluded.

Examples of parameterized types:

Vector<String>

Seq<Seq<A>>

Seq<String>.Zipper<Integer>

60

TYPES, VALUES, AND VARIABLES

Type Arguments and Wildcards

4.5.1

Collection<Integer>

Pair<String,String>

Examples of incorrect invocations of a generic type:

Vector<int> is illegal, as primitive types cannot be type arguments.

Pair<String> is illegal, as there are not enough type arguments.

Pair<String,String,String> is illegal, as there are too many type arguments.

A parameterized type may be an invocation of a generic class or interface which is nested. For example, if a non-generic class C has a generic member class D<T>, then C.D<Object> is a parameterized type. And if a generic class C<T> has a non-generic member class D, then the member type C<String>.D is a parameterized type, even though the class D is not generic.

Two parameterized types are provably distinct if either of the following conditions hold:

They are invocations of distinct generic type declarations.

Any of their type arguments are provably distinct.

4.5.1 Type Arguments and Wildcards

Type arguments may be either reference types or wildcards. Wildcards are useful in situations where only partial knowledge about the type parameter is required.

61

4.5.1

Type Arguments and Wildcards

TYPES, VALUES, AND VARIABLES

TypeArguments:

< TypeArgumentList >

TypeArgumentList:

TypeArgument

TypeArgumentList , TypeArgument

TypeArgument:

ReferenceType

Wildcard

Wildcard:

? WildcardBoundsopt

WildcardBounds: extends ReferenceType super ReferenceType

Example 4.5.1-1. Wildcards

import java.util.Collection; import java.util.ArrayList;

class Test {

static void printCollection(Collection<?> c) {

// a wildcard collection

for (Object o : c) { System.out.println(o);

}

}

public static void main(String[] args) { Collection<String> cs = new ArrayList<String>(); cs.add("hello");

cs.add("world");

printCollection(cs);

}

}

Note that using Collection<Object> as the type of the incoming parameter, c, would not be nearly as useful; the method could only be used with an argument expression that had type Collection<Object>, which would be quite rare. In contrast, the use of an unbounded wildcard allows any kind of collection to be used as a parameter.

Here is an example where the element type of an array is parameterized by a wildcard:

public Method getMethod(Class<?>[] parameterTypes) { ... }

62

TYPES, VALUES, AND VARIABLES

Type Arguments and Wildcards

4.5.1

Wildcards may be given explicit bounds, just like regular type variable declarations. An upper bound is signified by the following syntax, where B is the bound:

? extends B

Unlike ordinary type variables declared in a method signature, no type inference is required when using a wildcard. Consequently, it is permissible to declare lower bounds on a wildcard, using the following syntax, where B is a lower bound:

? super B

Example 4.5.1-2. Bounded Wildcards

boolean addAll(Collection<? extends E> c)

Here, the method is declared within the interface Collection<E>, and is designed to add all the elements of its incoming argument to the collection upon which it is invoked. A natural tendency would be to use Collection<E> as the type of c, but this is unnecessarily restrictive. An alternative would be to declare the method itself to be generic:

<T> boolean addAll(Collection<T> c)

This version is sufficiently flexible, but note that the type parameter is used only once in the signature. This reflects the fact that the type parameter is not being used to express any kind of interdependency between the type(s) of the argument(s), the return type and/or throws type. In the absence of such interdependency, generic methods are considered bad style, and wildcards are preferred.

Reference(T referent, ReferenceQueue<? super T> queue);

Here, the referent can be inserted into any queue whose element type is a supertype of the type T of the referent; T is the lower bound for the wildcard.

Two type arguments are provably distinct if one of the following is true:

Neither argument is a type variable or wildcard, and the two arguments are not the same type.

One type argument is a type variable or wildcard, with an upper bound (from capture conversion, if necessary) of S; and the other type argument T is not a type variable or wildcard; and neither |S| <: |T| nor |T| <: |S|.

Each type argument is a type variable or wildcard, with upper bounds (from capture conversion, if necessary) of S and T; and neither |S| <: |T| nor |T| <: |S|.

A type argument T1 is said to contain another type argument T2, written T2 <= T1, if the set of types denoted by T2 is provably a subset of the set of types denoted

63

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]