1.简单泛型类的定义
一个泛型类就是具有一个或多个类型变量的类。
例:public class Pair<T>{...}
可以有多个类型变量:public class Pair<T,U>{...}
类定义中的类型变量指定方法的返回类型以及域和局部变量的类型:private T first;
用具体的类型替换类型变量就可实例化泛型类型:Pair<String>
泛型类可看做是普通类的工厂。
2.泛型方法
例:public static <T>T getMiddle(T[] a){return a[a.length/2];}
调用一个泛型方法时,方法名前的尖括号中放入具体类型:
String middle=ArrayAlg.<String>getMiddle(names);
可以省略String类型参数:String middle=ArrayAlg.getMiddle(names);
3.类型变量的限定
例:
public static <T extends Comparable>T min(T[] a){
if(a==null||a.length==0)
return null;
T min = a[0];
for(int i=0;i<a.length;i++)
if(min.compareTo(a[i]>0)
min=a[i];
return min;
}
//泛型的min方法只能被实现了Comparable接口的类的数组调用。
//限定类型用"&"分隔:<T extends Comparable&Serializable>
4.泛型代码和虚拟机
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型。
原始类型用第一个限定的类型变量来替换,若没有就用Object替换。
public class Interval<T extends Comparable&Serializable> implements Serializable{
public Interval(T first,T second){
if(first.compareTo(second)<=0){
lower = first;
upper = second;
}
else{
lower = second;
upper = first;
}
}
...
private T lower;
private T upper;
}
原始类型如下:
public class Interval implements Serializable{
public Interval(Comparable first,Comparable second){
if(first.compareTo(second)<=0){
lower = first;
upper = second;
}
else{
lower = second;
upper = first;
}
}
...
private Comparable lower;
private Comparable upper;
}
4.1翻译泛型表达式
当程序调用泛型方法时,如果擦除返回类型,编译器插入强制类型转换。
例:
Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst();
//擦除getFirst的返回类型后将返回Object类型。
编译器自动插入Employee的强制类型转换。编译器把这个方法调用翻译为两条虚拟机指令:
(1)对原始方法Pair.getFirst的调用;
(2)将返回的Object类型强制转换为Employee类型。
4.2翻译泛型方法
虚拟机中,用参数类型和返回类型确定一个方法。
4.3调用遗留代码
5.约束与局限性
5.1不能用基本类型实例化类型参数(因为类型擦除)Pair<double> -> Pair<Double>
5.2运行时类型查询只适应于原始类型。
getClass方法总是返回原始类型:
Pair<String> stringPair = ...;
Pair<Employee> employeePair = ...;
stringPair.getClass()==employeePair.getClass();//Pair.class
5.3不能抛出也不能捕获泛型类实例
5.4不能声明参数化类型的数组
Pair<String>[] table = new Pair<String>[10];//错误
ArrayList<Pair<String>> = new ArrayList<Pair<String>>[10];//既安全又有效
5.5不能实例化类型变量public Pair(){first = new T();second = new T();}//错误
5.6泛型类的静态上下文中类型变量无效
不能在静态域或方法中引用类型变量。
5.7注意擦除后的冲突
6.泛型类型的继承规则
Pair<Manager>并不是Pair<Employee>的子类,
泛型类可以扩展或实现其他的泛型类。
ArrayList<T>可实现List<T>接口;
ArrayList<Manager>可转换为List<Manager>
7.通配符类型
public static void printBuddies(Pair<Employee> p){
//不能将Pair<Manager>传递给这个方法;
Employee first = p.getFirst();
Employee second = p.getSecond();
System.out.println(first.getName()+"and"+second.getName()+"are buddies";
}
//使用通配符:Pair<Manager>是Pair<? extends Employee>的子类型
public static void printBuddies(Pair<? extends Employee> p){
//可以将Pair<Manager>传递给这个方法;
//不能调用setFirst方法,可以调用getFirst
//安全的访问器,不安全的更改器
...
}
7.1通配符的超类型限定
? super Manager //Manager的所有超类型
与前面介绍相反,可以为方法提供参数,但不能使用返回值。
void setFirst(**? super Manager**)
**? super Manager** getFirst()
//可用Manager对象(或子类型)调用setFirst,不能用Employee对象调用;
//若调用getFirst,返回的对象类型得不到保障
!!带有超类型的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。
7.2无限定通配符Pair<?>
7.3通配符捕获
8.反射和泛型