【0】README
0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 无限定通配符+通配符捕获 的相关知识;
【1】无限定通配符相关
1.1)无限定通配符: 如Pair< ?>;
- 1.1.1)类型 Pair< ?> 有方法如下所示:
? getFirst() : 返回值只能赋给 Object,;
void setFirst(?) : setFirst 方法不能被调用, 甚至不能用 Object 调用;
- 1.1.2)Pair< ?> 和 Pair 本质不同在于: 可以用任意 Object对象调用原始的 Pair类的setObject 方法; (也可以调用 setFirst(null));
1.2)为什么要使用 无限定通配符?
- 1.2.1)看个荔枝:下面方法将用来测试一个 pair 是否包含一个 null 引用, 它不需要实际的类型;
public static boolean hasNulls(Pair<?> p)
{
return p.getFirst() == null || p.getSecond() == null;
}
- 1.2.2)通过将 hasNulls 转换成泛型方法, 可以避免使用 通配符类型:
public static <T> boolean hasNulls(Pair<T> p) , 但是带有通配符的版本可读性更强了;
【2】通配符捕获相关
2.1)出现的问题:
- 2.1.1)通配符不是类型变量, 不能在编写代码中使用 ? 作为一种类型, 下面代码是非法的:
? t = p.getFirst(); // ERROR
p.setFirst(p.getSecond());
p.setSecond(t);
2.2)解决方法: 编写一个辅助方法 swapHelper, 如下所示:
public static <T> void swapHelper(Pair<T> p)
{
T t = p.getFirst();
p.setFirst(p.getSecond());
p.setSecond(t);
}
Attention) swapHelper 是一个 泛型方法, 而 swap不是, 它具有固定的Pair
public static void swap(Pair<?> p)
{ swapHelper(p); }
2.4)当然, 在这种情况下, 并不是一定要使用通配符。
- 2.4.1)我们已经直接实现了 没有 通配符的泛型方法 void swap(Pair p) , 看个荔枝:
public static void maxminBonus(Manager[] a, Pair<? super Manager> result)
{
minmaxBonus(a, result);
PairAlg.swap(result) ; //OK--swapHelper captures wildcard type
}
- 在这里,通配符捕获机制是不可避免的;
- 2.4.2)通配符捕获只有在很多限制的情况下才是合法的。
- 编译器必须能够确信通配符表达的是 单个、确定的类型;如, ArrayList< Pair< T>> 中的T 永远不能捕获 ArrayList< Pair< ?>> 中的通配符;