1,List
2,List<Object>
3,List<Number>
4,List<?>
5,List<? extends Number>
6,List<? super Long>
普通的泛型使用估计没啥问题,但是带上 ? 的泛型就会变得很复杂。
对于 <? super T> 和 <? extends T> 看看这个例子:
如果要将某一个数组中的元素拷贝至另一个的话
1,先看看这个方法签名:
1
|
public
static
<T>
void
copy(List<T> src, List<T> dest)
|
如果 src 和 dest 是相同泛型参数的话,这个签名是没有问题,但是由于泛型类与数组不一样,由于泛型类并不具有协变性,也就是说下面的代码是错误的:
1
|
List<Object> objs =
new
ArrayList<Long>();
|
数组是协变性的,下面的代码是正确的:
1
|
Object[] objs =
new
Long[
4
];
|
用这个 copy 方法的话,如果 src 是 List<Long>,而 dest 是 List<Object> 的话,这样就会产生编译错误。但是实际上 List<Long> 中的每一个元素是可以赋值给 List<Object> 的,因此这个 copy 方法签名还有待完善。
由于泛型类不具有协变性,但是 Java 的泛型提供了一个通配符类型 ? 使用这个可以将泛型类变成协变的,下面的代码是正确的:
1
|
List<?
extends
Object> objs =
new
ArrayList<Long>();
|
<? extends Object> 表示泛型是 Object 或者是 Object 的子类型,同理
<? super Long> 表示泛型是 Long 或者是 Long 的父类型。
这样就可以把 copy 方法完善成为:
1
|
public
static
<T>
void
copy (List<?
extends
T> src, List<?
super
T> dest)
|
至于其他的,看看下面的语句哪些正确的,哪些是不正确的?
Pair 是个泛型类,SubTypeOfPair 是 Pair 的子类
1
2
3
4
5
|
Collection<Pair<String, Long>> c1 =
new
ArrayList<Pair<String, Long>>();
Collection<Pair<String, Long>> c2 = c1;
// s1
Collection<Pair<String, ?>> c3 = c1;
// s2
Collection<?
extends
Pair<String, ?>> c4 = c1;
// s3
|
1
2
3
4
5
6
|
Collection<SubTypeOfPair<String, Long>> c1 =
new
ArrayList<SubTypeOfPair<String, Long>>();
Collection<Pair<String, Long>> c2 = c1;
// s4
Collection<SubTypeOfPair<String, Long>> c3 = c1;
// s5
Collection<Pair<String, ?>> c4 = c1;
// s6
Collection<?
extends
Pair<String, ?>> c5 = c1;
// s7
I will try to explain the Java generics using two simple rules. These rules suffice to answer your question and are basically enough to remember for almost any case:
Case
|