Generic Types
A generic type is a generic class or interface that is parameterized over types.
A Simple Box Class
public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
这种写法的主要问题和上一章举的例子是一样的。
A Generic Version of the Box Class
A generic class is defined with the following format:
class name<T1, T2, ..., Tn> { /* ... */ }
// Tn: type parameters (also called type variables)
下面我们把Box改成generic版本:
/**
* Generic version of the Box class.
* @param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Type Parameter Naming Conventions
- E - Element (used extensively by the Java Collections Framework)
- K - Key
- N - Number
- T - Type
- V - Value
- S,U,V etc. - 2nd, 3rd, 4th types
Invoking and Instantiating a Generic Type
Box<Integer> integerBox = new Box<Integer>();
The Diamond(<>)
从Java 7开始,可以简写成以下形式:
Box<Integer> integerBox = new Box<>();
因为编译器可以推断出integerBox是Box<Integer>类型,具体可以看后面的章节Type Inference。
Multiple Type Parameters
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
public class OrderedPair<K, V> implements Pair<K, V> {
private K key;
private V value;
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Parameterized Types
You can also substitute a type parameter (i.e., K or V) with a parameterized type (i.e., List<String>).
OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));
Type Parameter and Type Argument
Type Parameter and Type Argument Terminology: Many developers use the terms "type parameter" and "type argument" interchangeably, but these terms are not the same. When coding, one provides type arguments in order to create a parameterized type. Therefore, the T in Foo<T> is a type parameter and the String in Foo<String> f is a type argument.
Raw Types
A raw type is the name of a generic class or interface without any type arguments.
Box
is the raw type of the generic type Box<T>
:
Box rawBox = new Box();
为了向后兼容,允许将参数化类型赋给其原始类型:
Box<String> stringBox = new Box<>();
Box rawBox = stringBox; // OK
但是,如果将原始类型赋给参数化类型,你会收到warning:
Box rawBox = new Box(); // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox; // warning: unchecked conversion
如果你使用原始类型调用泛型类型中定义的方法,你也会收到warning:
Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8); // warning: unchecked invocation to set(T)
The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime. Therefore, you should avoid using raw types.