有书共读】java核心技术卷1--第8章
主要内容:
1、定义简单泛型类
5、通配符类型
泛型程序设计:编写的代码可以被很多不同类型的对象所使用。
类型参数的好处在于使得程序具有更好的可读性和安全性。
1、定义简单泛型类
一个泛型类就是具有一个或多个类型变量的类。
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 T getSecond() { return second; }
public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}
Pair类引入了一个类型变量T,用<>括起来,放在类名后。泛型类可以有多个类型的变量。如public class Pair<T,U> {…},其中第一个域和第二个域使用不同的类型。
2、泛型方法
泛型方法可以定义在普通类中,也可以定义在泛型类中。
定义一个带有类型参数的简单方法。
Class ArrayAlg{
public static <T> T getMiddle(T….a)
{
Return a[a.length / 2];
}
}
调用一个泛型方法时,在方法名前的尖括号中放入具体的参数类型:
String middle = ArrayAlg.<String>getMiddle(“John”,”Q.”,”Public”);
3、类型变量的限定
有时需要对类或方法的类型变量加以约束。例:计算数组中最小的元素
class ArrayAlg
{
public static <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;
}
}
从min方法中,变量smallest类型为T,意味着它可以作为一个类的对象。
为了确信T所属的类有compareTo方法,将T限制为实现了Compareable接口的类。可以通过对类型变量T设置限定(bound)实现这点:
public static <T extends Compareable> T min(T[] a)…
一个类型变量获通配符可以有多个限定,例如:
T extends Compareable & Serializable
限定类型用‘&‘分隔,逗号用来分隔类型变量。
4、约束与局限性
(1)不能使用基本类型实例化类型参数,不能使用类型参数代替基本类型
(2)运行时类型查询只适用于原始类型
(3)不能创建参数化类型的数组
(4)Varargs警告,可以采用两种方法来抑制这个警告,一是可以包含addAll调用的方法增加注解@SuppressWarning(“unchecked”),或者在JavaSE7中,可以用@SafeVarargs直接标注addAll方法:
@SafeVarargs
public static <T> void addAll(Collection<T> coll,T… ts)
(5)不能实例化类型变量, 不能使用像new T(),new T[…] 或T.class这样的表达式中的类型变量。
(6)不能构造泛型数组
(7)泛型类的静态上下文中类型变量无效,不能在静态域或方法中引用类型变量。
(8)不能抛出或捕获泛型类的实例,甚至泛型类扩展Throwable都是不合法的。
(9)可以消除对受查异常的检查。Java异常处理的一个基本原则是,必须为所有受查异常提供一个处理器。不过可以利用泛型消除这个限制。关键在于以下方法:
@SuppressWarning(“unchecked”)
public static<T extends Throwable> void throwAs(Throwable) throws T
{
thro(T) e;
}
(10)注意擦除后的冲突。当泛型类型被擦除时,无法创建引发冲突的条件。
5、通配符类型
图8-1 使用通配符的子类型关系
(2)通配符的超类型限定
通配符限定与类型变量限定十分类似,但是,还有一个附加的能力,即可以指定一个超类型限定(supertype bound),如
? super Manager
这个通配符限制为Manager的所有超类型。
(3)无限定通配符。还可以使用无限定的通配符,例如Pair<?>
(4)通配符捕获。通配符捕获只有在许多限制的情况下才是合法的。编译器必须能够确信通配符表达的是单个、确定的类型。
6、反射和泛型
反射允许在运行时分析任意的对象。