泛型类
泛型类就是有一个或多个类型变量的类。
以ArrayList集合为例,其格式如下:
class ArrayList<E>{
public boolean add(E e){ }
public E get(int index){ }
....
}
类型变量E(也可以是其他任意字母),用尖括号<>括起,放在类名的后面。使用多个类型变量时用逗号分隔,如<T, U, S>。
类型变量在整个类定义中用于指定方法的返回类型以及字段和局部变量的类型。
在创建对象时确定泛型类型。
泛型方法
定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
示例:
public class MyGenericMethod {
public <MVP> void show(MVP mvp) {
System.out.println(mvp.getClass());
}
public <MVP> MVP show2(MVP mvp) {
return mvp;
}
}
泛型方法可以在泛型类中定义,也可以在普通类中定义。类型变量放在修饰符(如上述的public)后面,并放在返回类型的前面。
调用一个泛型方法时,可以把具体类型包围在尖括号中,放在类的后面,方法名的前面。实际上大多数情况下,这里的具体类型可省。
泛型接口
定义格式:修饰符 interface 接口名<代表泛型的变量> { }
示例:
public interface MyGenericInterface<E>{
public abstract void add(E e);
public abstract E getE();
}
实现时,变量类型的确定同样使用尖括号将具体类型括起,放在接口名后。也可以在实现时仍然使用泛型,直到创建对象时才确定。
泛型的实现细节
1.虚拟机没有泛型对象,只有普通的类和普通的方法。
2.定义一个泛型类型后,类型变量会被擦除,并替换为其限定类型(无限定则为Object),若有多个限定类型,则使用第一个限定来替换类型变量。
3.为了保证类型的安全性,编译器会在必要时插入强制类型转换。
4.为提高效率,应将标签接口(即没有方法的接口)放在限定列表的末尾。
5.类型擦除可能会与多态发生冲突,Java选择使用合成桥的方法,在类中生成一个参数类型为Object的方法,由该方法帮助其实现多态的特性。
泛型的限制与局限性
1.不能用基本类型实例化类型参数。
2.运行时的类型检查只适用于原始类型。
如,下述语句仅仅测试a是否是任意类型的Pair:
if ( a instanceof Pair<String>)
getClass方法同样如此,它总是返回原始类型。
3.不能实例化参数化类型的数组。声明仍然合法,只是不能初始化。
4.不能实例化类型变量。
5.不能构造泛型数组。
6.泛型类的静态上下文中类型变量无效。
7.不能抛出或捕获泛型类的实例。
8.可以取消对检查型异常的检查。