泛型概念
先来看看泛型类的示例:
|
|
当然,定义泛型类可以引入多个类型变量,例如:
|
|
泛型类可以看作普通类的工厂,还可以在普通类中定义一个泛型方法:
|
|
这里类型变量放在修饰符public static后面,实际调用时:
|
|
大多数情况下你可以省略String
,直接
|
|
但前提是参数都是这些类的超类唯一,编译器才不会报错
|
|
我们知道在jvm层面上没有泛型的概念,类型变量都会被原始类型所替代,无限定的就用Object,如果有多个限定类型,就用第一个替换,例如上例中会用Comparable替换。
泛型约束和限制
泛型不能用于基本类型
运行时类型查询只适用于原始类型,例如
123Pair<A> a = new Pair<A>();Pair<B> b = new Pair<B>();a.getClass() == b.getClass(); // 相等,都是Pair.class不能抛出也不能捕获泛型类实力
不能声明泛型参数化的数组
1ArrayList<String>[] arr = new ArrayList<String>[10];不能实例化泛型实例变量,如Pair的构造器这样就是非法的:
1234public Pair() {first = new T(); // ERRORsecond = new T();}
泛型继承
如果A是B的子类,那么Pair<A>
不是Pair<B>
的子类。
数组情况则不同,A是B的子类,可以将
A[]
赋值给B[]
但是将参数化类型转换成原始类型会导致类型错误么?很遗憾,编译器只是会给个warning,可以编译:
|
|
这看起来比较恐怖,但是当使用getFirst()
调用转换成Manager时,会抛出ClassCastException
通配符
之前代码中有Pair<? extends Employee>
表示类型参数是Employee的子类
|
|
泛型类翻译以后:
|
|
setFirst方法只知道需要Employee的子类型,但是确切不知道是哪种类型,因此连编译都不能通过。除了extends关键字还存在super关键字表示父类,例如Pair<? super Manger>
,那么经过泛型翻译以后,Pair<? super Manager>
有以下方法:
|
|
这时setFirst方法可以调用Manager对象以及Manager的子类型了,再看下面一个典型的例子:
|
|
因此直观地将,带有super限定的通配符可以向泛型对象写入,带有extends类型限定的通配符可以从泛型对象读取。
无限定通配符
无限定通配符是指Pair<?>
,这看起来跟原始的Pair类型一样,类型Pair<?>有如下方法:
|
|
这里getFirst方法返回值只能赋给一个Object,setFirst方法不能被调用