泛型类
泛型类就是具有一个或多个类型变量的类,对于这个类来说,只关注泛型,而不会为数据存储的细节烦恼
public class Pair<T>
{
private T first;
private T second;
...
}
泛型类可以有多个类型变量,
`public class Pair<T, U> { . . .} 第一个域和第二个域使用不同的类型
变量E表示集合的元素类型,K和V分别表示表的关键字和值的类型,T和U表示任意类型
泛型方法
带有参数类型的简单方法,
class ArrayAlg
{
public static <T> T getMiddle(T...a)
{
retuen a[a.length / 2];
}
}
类型变量在修饰符后, 返回类型前。
泛型方法可以定义在普通类,也可以定义在泛型类,当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型。
String middle = ArrayAlg.<String>getMiddle("a","cs","wd");
类型变量的限定
有时类或方法需要对类型变量加以约束,例如要计算数组中的最小元素
class ArrayAlg
{
public static <T> min(T[] a)
{
if (a == null || a.length == 0) return null;
T smallest = a[0]
for(int i; i< a.length; i++)
if(smallest.compareTo(a[i]) > 0) smallest = a[i];
return smallest;
}
}
min方法内部,smallest的类型是T,意味着可以是任何对象,无法确定T所属的类有compareTo方法,
解决办法:将T限制为实现了Comparable接口的类(只含有一个方法compareTo的标准接口),可以通过对类型变量设置限定(bound)实现
public static <T extends Comparable> T min(T[] a)...
为什么用extends而不是impements,comparable不是接口吗?
<T extends BoundingTypr>
T应该是绑定类型的子类型(subtype)T和绑定类型可以是类,也可以是接口,选择关键字extends的原因是更接近子类的概念。
一个类型变量或通配符可以有多个限定
T extends Comparable & Serialiazble
泛型代码和虚拟机
虚拟机没有泛型类型对象,所有对象都属于普通类。
类型擦除
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型(raw type)原始类型的名字就是删去类型参数后的泛型类型名,擦除(erased)类型变量,并替换为限定类型(无限定的变量用Object)
翻译泛型表达式
当程序调用泛型方法时,如果擦除返回类型, 编译器插入强制类型转换,
Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst();
擦除getFirst的返回类型后将返回Object类型,编译器自动插入Employee的强制类型转换,编译器把这个方法调用翻译为两条虚拟机指令;
- 对原始方法Pair.getFirst的调用
- 将返回的Object类型强制转换成Employee类型。