定义泛型类
泛型程序的设计是一个非常复杂的事情,尤其是一个运行良好的程序
//在类上已经声明的<T>,在方法上面可以不再声明,重复声明会出异常
public class Pair<T> {
private T first;
private T second;
public Pair() {
this.first = null;
this.second = null;
}
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
public void setFirst(T first) {
this.first = first;
}
public void setSecond(T second) {
this.second = second;
}
}
定义泛型方法
//hashMap中的put方法,泛型,V是返回值
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
类型变量的限定
/**
*
* @param a
* @param <T> 有时候需要对类型变量做出限定,使用extends.
* @return
*/
public static <T extends Comparable&Serializable> T min(T[] a) {
if (a == null || a.length == 0)
return null;
T smallest = a[0];
for (int i = 1; i < a.length; i++) {
if (smallest.compareTo(a[i]) > 0) smallest = a[i];
}
return smallest;
}
- 为什么使用extends,不使用implements,Comparable是一个接口,T是Comparable的子类,可能是接口,可能是类,extends更加符合情况。
- 限定类型用&来表示,逗号用来分隔类型变量
- 如果有类作为限定,必然是限定列表的第一个
- tagging接口(标签接口)也就是没有方法的接口放在最后一个限定;
泛型擦除
- 虚拟机没有泛型类型对象——所有的对象都属于普通类。
- 泛型——类型擦除——原始类型(擦除泛型参数后的类型名)
- 类型变量变成限定类型,没有限定类型的使用Object
- 多个限定的使用第一个;
约束和局限性
- 不能用基本类型实例化类型参数:只能有
Pair<Double>
,不能有Pair<double>;
- 所有的类型检查只产生原始类型:
if (args instanceof Pair<T>)
错误的- 不能创建参数化类型的数组:
Pair<String> table = new Pair<>[10];
错误的- 不能实例化类型变量:
- 不能构造泛型数组
- 不能在静态域或者方法中引用类型变量
- 不能抛出或者捕获泛型类的实例
- 可以消除对受检异常的检查