1、为什么要使用泛型程序设计
泛型程序设计意味着编写的代码可以被很多不同类型的对象所使用。
2、定义简单泛型类
public class Pair<T>
{
private T first;
private T second;
public Pair() { first = null; second = null;}
public Pair(T first ,T second) {this.first = first; this.second = second; }
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
}
泛型也可以有多个类型变量
public class Pair<T,U> {....}
变量E表示集合的元素类型,K和V分别表示表的关键字与值的类型。T(需要的时候还可以用临近的U、S)表示“任意类型”。
3、泛型方法
class ArrayAlg
{
public static <T> getMiddle(T... a)
{
return a[a.length/2];
}
}
4、类型变量的限定
类或方法需要对类型变量加以约束
public static <T extends Coiparab1e> T a) . . .
将T限制为实现了Comparable接口
一个类型变量或通配符可以有多个限定。例如
T extends Comparable & Serializable
限定类型用“ &” 分隔,而逗号用来分隔类型变量。
5、泛型代码和虚拟机
5.1 类型擦除
无论何时定义一个泛型类型,都会自动提供一个相应的原始类型。原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用Object)
原始类型用第一个限定的类型变量来替换, 如果没有给定限定就用 Object 替换。
5.2 翻译泛型表达式
5.3 翻译泛型方法
总之,需要记住有关Java 泛型转换的事实:
•虚拟机中没有泛型,只有普通的类和方法。
•所有的类型参数都用它们的限定类型替换。
•桥方法被合成来保持多态。
•为保持类型安全性,必要时插人强制类型转换。
5.4 调用遗留代码
6、 约束与局限性
6.1 不能用基本类型实例化类型参数
6.2 运行时类型查询只适用于原始类型
6.3 不能创建参数化类型的数组
6.4 Varargs 警告
@SafeVarargs
public static <T> void addAll(Collection<T> coll, T... ts)
6.5 不能实例化类型变置
6.6 不能构造泛型数组
提供一个数组构造器表达式:
String口 ss = ArrayAlg.minmax(String口::new,"Tom", "Dick", "Harry");
构造器表达式String::new 指示一个函数,给定所需的长度,会构造一个指定长度的
String 数组。
6.7 泛型类的静态上下文中类型变量无效
6.8 不能抛出或捕获泛型类的实例
不过,在异常规范中使用类型变量是允许的。以下方法是合法的:
public static <T extends Throwable〉void doWork(T t) throws T // OK
try
{
do work
}
catch (Throwable real Cause)
{
t.initCause( real Cause) ;
throw t;
}
}
6.9 可以消除对受查异常的检查
Java 异常处理的一个基本原则是,必须为所有受查异常提供一个处理器。不过可以利用
泛型消除这个限制。关键在于以下方法:
6.10
7 泛型类型的继承规则
8 反射和泛型
8.1 泛型Class 类
•T newInstanceO
返回无参数构造器构造的一个新实例。
• T cast(Object obj)
如果obj 为null 或有可能转换成类型T,则返回obj ; 否则拋出BadCastException异常。
•T[ ] getEnumConstants( ) 5.0
如果T 是枚举类型,则返回所有值组成的数组,否则返回null
• Class<? super T> getSuperclass( )
返回这个类的超类。如果T 不是一个类或Object 类,则返回null
• Constructor<T> getConstructor(Class. • • parameterTypes) 1.1
• Constructor<T> getDeclaredConstructor(Class. • . parameterTypes) 1.1
获得公有的构造器,或带有给定参数类型的构造器。
•T newlnstance(0bject . . . parameters)
返回用指定参数构造的新实例。
8.2 使用Class<T> 参数进行类型匹配
有时,匹配泛型方法中的Class<I> 参数的类型变量很有实用价值。下面是一 标准的示例:
public static <T> Pai r<T> makePair(Class<T> c) throws InstantiationException,
IllegalAccessException
{
return new Pairofc.newInstanceO » c.newInstanceO);
}
如果调用
makePair(Employee.class)
Employee.class 是类型Class<Employee> 的一个对象。makePair 方法的类型参数T 同Employee
匹配,并且编译器可以推断出这个方法将返回一个Pair<Employee>。
8.3 虚拟机中的泛型类型信息