Java--通配符类型

2018-02-27 11:50:43来源:oschina作者:Superheros人点击

分享

Java有三种通配符限定:子类型限定通配符、超类型限定通配符、无类型通配符。


在泛型程序设计语法中,考察了下面的Pair泛型类,也提到了泛型的继承规则。无论S与T是什么关系,Pair和Pair没有任何关系。但当我们有这方面的需求时,就可以使用通配符类型。


public class Pair{
private T first;
private T second;public T getFirst(){ return first; }
public T getSecond(){ return second; }
public void setFirst(T newVal){ first = newVal; }
public void setSecond(T newVal){ second = newVal; }
}

通配符类型中,允许类型参数变化。


1、子类型限定通配符


Pair<? extends Employee>

表示任何Pair泛型类型,它的参数是Employee的子类。比如如果Manager是Employee的子类,那么Pair是Pair<? extends Employee>的子类型。


注意:子类型限定通配符可以从泛型类读取,但不能向泛型类写入。用Pair泛型类举例,上面的setFirst()方法和getFirst()方法应该是下面这样:


? extends Employee getFirst()//子类型限定下的getFirst方法
void setFirst(? extends Employee)//子类型限定下的setFirst方法

因为上溯造型,无论是什么子类型,都可以上溯造型为Employee, 所以我们可以调用getFirst方法进行读取;但setFirst方法不行,编译器只知道需要Employee的一个子类型,但不知道具体类型。它拒绝传递任何特定的类型,毕竟?不能用来匹配。


2、超类型限定通配符


Pair<? super Manager>

这个通配符限制为Manager的所有超类型。带有超类型的通配符可以向泛型对象写入,但不能从泛型对象读取。


void setFirst(? super Manager)
? super Manager getFirst()

上面不是真正的Java语法,但可以了解编译器知道什么。我们可以调用setManager方法,并传入Manager对象或者它的子类型对象,但不能传入Manager的超类;另外,调用getFirst方法不能保证返回对象的类型。只能把它赋给一个Object。


直观的讲,带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。


3、无限定通配符


Pair<?>

类型Pair<?>的两个方法可以看作:


? getFirst()
void setFirst(?)

getFirst()的返回值只能赋给一个Object。setFirst()方法不能被调用,甚至不能被Object调用。不过可以调用setFirst(null)。


Pair<?>和Pair本质区别:可以用任意Object对象调用原始类型的setObject方法(涉及到类型擦除问题)。


通配符捕获:


例如我们要写一个交换方法,交换的时候必须临时保存第一个元素,但通配符不是类型变量,因此不能像下面这样写:


public static void swap(Pair<?> p){
? t = p.getFirst();//Error
p.setFirst(p.getSecond);
p.setSecond(t);
}

上面这种方法不可取,但我们可以通过引入一个辅助方法来实现:


public static void swapHelper(Pair p){
T t = p.getFirst();
p.setFirst(p.getSecond);
p.setSecond(t);
}

注意,swapHelper是一个泛型方法,但swap不是,swap具有固定的Pair<?>类型的参数。现在可以通过swap调用swapHelper:


public static void swap(Pair<?> p){ swapHelper(P); }

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台