泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。
1.类型参数的好处
在Java中增加泛型类之前,泛型程序设计是用继承实现的。ArrayList类只维护一个Object引用的数组。当获取一个值时必须进行强制类型转换。
如今,ArrayList类有一个类型参数用来指示元素的类型:
ArrayList<String> files = new ArrayList();
这使得代码具有更好的可读性。
2.通配符类型的好处
但是,实现一个泛型类并没有那么容易。对于类型参数,程序员们可能想内置所有的类。例如:ArrayList类有一个方法addAll用来添加另一个集合的全部元素,可能想要将ArrayList<Manager>中的所有元素添加到ArrayList<Employee>中去。然而,反过来就不行了。
Java语言的设计者发明了一个具有独创性的新概念---通配符类型,解决了上述问题。通配符类型非常抽象,然而,它们能让库的构建者编写出尽可能灵活的方法。
3.定义简单的泛型类和泛型方法
一个泛型类就是具有一个或多个类型变量的类。例如:
- 泛型类
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() {retrun first;}
public T getSecond() {return second;}
public void setFirst(T newValue) {first = newValue;}
public void setSecond(T newValue) {second = newValue;}
}
Pair类引入了一个类型变量T,用尖括号< >括起来,并放在类名的后面。泛型类可以有多个类型变量。例如,可以定义Pair类,其中第一个域和第二个域使用不同的类型:
public class Pair<T, U> {...}
- 泛型方法
定义一个带有类型参数的方法:
class ArrayAlg {
public static <T> T getMiddle(T... a) {
return a[a.length / 2];
}
}
这是一个泛型方法,可以从尖括号和类型变量看出这一点。类型变量放在修饰符(public static)的前面,返回类型的后面。泛型方法可以定义在普通类中,也可以定义在泛型类中。
4.类型变量的限定
有时,类或方法需要对类型变量加以约束。例,计算数组中最小的元素:
class ArrayAlg {
public static <T> 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;
}
}
变量smallest类型为T,这意味着它可以是任何一个类的对象。怎样才能确信T所属的类有compareTo方法呢?可以将T限制为实现了Comparable接口的类。可以通过对类型变量T设置限定实现这一点:
public static <T extends Comparable> T min(T[] a)...
下面的记法:
<T extends BoundingType>
表示T应该是绑定类型的子类型。T和绑定类型可以是类,也可以是接口。一个类型变量或是通配符可以有多个限定,例如:
T extends Comparable & Serializable
限定类型用"&"分隔,而逗号用来分隔类型变量。限定中至多有一个类,如果用一个类作为限定,它必须是限定列表中的第一个。
5.泛型代码和虚拟机
- 虚拟机中没有泛型,只有普通的类和方法
- 所有的类型参数都用他们的限定类型替换,没有限定类型的用Object替换
- 桥方法被合成来保持多态
- 为保持类型安全性,必要时插入强制类型转换
网友评论