一、为什么要使用泛型程序设计
泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。
类型参数是魅力在于:使得程序具有更好的可读性和安全性。
二、定义简单泛型类
一个泛型类就是具有一个或多个类型变量的类。
在Java库中,使用变量E表示集合的元素类型;K和V分别表示表的关键字和值的类型;T(需要时还可以用临近的字母U和S)表示“任意类型”。
泛型类可看做普通类的工厂。
三、泛型方法
泛型方法可以定义在普通类中,也可以定义在泛型类中。
四、类型变量的限定
可以通过对类型变量T设置限定实现将T限制为实现了某个接口的类。
语法:
<T extends BoundingType>
表示T应该是绑定类型的子类型。T和绑定类型可以是类,也可以是接口。
限定类型用“&”分隔,而逗号用来分隔类型变量。
在Java的继承中,可以根据需要拥有多个接口超类型,但限定中至多有一个类。
如果用一个类作为限定,它必须是限定列表中的第一个。
五、泛型代码和虚拟机
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型。原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用Object)。
当程序调用泛型方法时,如果擦除返回类型,编译器插入强制类型转换。
虚拟机中没有泛型,只有普通的类和方法。
所有的类型参数都用它们的限定类型替换。
桥方法被合成来保持多态。为保持类型安全性,必要时插入强制类型转换。
六、约束和局限性(大部分限制是由类型擦除引起的)
1、不能用基本类型实例化类型参数。
2、运行时类型查询只适用于原始类型。
3、不能创建参数化类型的数组。
4、Varargs警告,可以使用@SafeVarargs标注来消除创建泛型数组的有关限制。
5、不能实例化类型变量。
6、不能构造泛型数组。
7、泛型类的静态上下文中类型变量无效。
8、不能抛出或捕获泛型类的实例。
9、通过使用泛型类,擦除和@SuppressWarnings注解,就能消除Java类型系统的部分基本限制。可以消除对受查异常的检查。
10、注意擦除后的冲突。
七、泛型类型的继承规则
无论S和T有什么关系,通常,Pair<S>和Pair<T>没有什么联系。
八、通配符类型
通配符的超类型限定:带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。
无限定通配符:Pair<?>和Pair本质的不同在于:可以用任意Object对象调用原始Pair类的setObject方法。