泛型类型必须是引用类型
ArrayList<int> intList = new ArrayList<>(); //is wrong!
应写成:
ArrayList<Integer> intList = new ArrayList<>();
自动拆装箱
ArrayList<Integer> intList = new ArrayList<>();
intList.add(5);
Java 会自动将 5 包装为 new Integer(5),这个过程称为自动装箱。
ArrayList<Integer> intList = new ArrayList<>();
intList.add(5);
Integer integerObject = intList.get(0);
int i = intList.get(0);
Java 先将 5 自动装箱,并添加到 intList 中,然后 intList 中的第一个元素赋值给了一个 Integer 类型的变量,无需进行类型转换,然后 intList 中的第一个元素自动转换为一个 int 基本类型,并赋值给了 i ,这个过程称为自动拆箱。
实例化泛型类
new ClassName<E>()
**注意:**不要因为实例化泛型类的语句而误以为泛型类的构造方法为
public ClassName<E>() {...}
泛型类的构造方法和一般的类的构造方法是一样的。
多参数泛型
泛型类有多个参数时,把所有的参数一起放进尖括号内并用逗号隔开,比如:
class ClassName<E1, E2, E3> {...}
原始类型
没有指定具体类型的泛型类和泛型接口称为原始类型,用于和早期的 Java 版本向后兼容。
ClassName c = new ClassName();
//等价于
ClassName<Object> c = new ClassName<Object>();
消除泛型
泛型在运行时是被消除的!
泛型存在于编译时,一旦编译器确认泛型类型是安全使用的,就会将它转换为原始类型,如果泛型受限,编译器会用受限类型替换。比如:
public static <E> void printE(E e) {
System.out.println(e);
}
转换为
public static void printE(Object e) {
System.out.println(e);
}
public static <E extends Comparable<E>> E max(E e1, E e2) {
if (e1.compareTo(e2) > 0)
return e1;
else
return e2;
}
替换为
public static Comparable max(Comparable e1, Comparable e2) {
if (e1.compareTo(e2) > 0)
return e1;
else
return e2;
}
运行时,不管有多少种具体的泛型类,都只会有一个类被加载到 JVM 中。
ArrayList<Integer> intList = new ArrayList<>();
ArrayList<Double> doubleList = new ArrayList<>();
编译时存在ArrayList<Integer>
和ArrayList<Double>
两种类型,但是运行时只有一个 ArrayList 类被加载到 JVM 中。intList 和 doubleList 都是 ArrayList 的实例。下面两条语句的执行结果都是 true:
System.out.println(intList instanceof ArrayList);
System.out.println(doubleList instanceof ArrayList);
但是语句System.out.println(intList instanceof ArrayList<Integer>);
的输出结果是 false。
泛型类型的使用限制
因为运行时泛型类型会被消除,所以使用泛型类型是有一些限制的。
- 限制1:不能使用 new E()
E e = new E(); //is wrong!
- 限制2:不能使用 new E[]
E[] e = new E[10]; //is wrong!
规避方法:
E[] e = (E[])new Object[10];
但还是会有一个免检的编译警告。
- 限制3:在静态上下文中不允许类的参数是泛型类型
public class Test<E> {
pulic static void m(E e1) { } //Illegal
public static E e2; //Illegal
}
- 限制4:异常类不能是泛型的
public class MyException<E> extends Exception { } //Illegal