public class Hello_2 {
public static void main(String[] args) {
Pair<Integer> p = new Pair<>(123, 456);
int n = add(p);
System.out.println(n);
}
/*
接受Integer类型,变成Pair<Integer>,setFirst(Integer first)无法接受Integer类型
但是可以返回Integer类型,换言之:“只可读,不可写”
*/
static int add(Pair<? extends Number> p) {
// 正常返回结果
Number first = p.getFirst();
Number last = p.getLast();
// 编译出错
// p.setFirst(new Integer(first.intValue() + 100));
// p.setLast(new Integer(last.intValue() + 100));
return p.getFirst().intValue() + p.getLast().intValue();
}
}
class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() {
return first;
}
public T getLast() {
return last;
}
public void setFirst(T first) {
this.first = first;
}
public void setLast(T last) {
this.last = last;
}
}
该通配符限定泛型类型T的上界(包括自身)
如上述示例代码,如果去掉setFirst等的注释,那么会出现一个编译错误。
为什么
p
的定义是Pair<? extends Number>
,那么setFirst(? extends Number)
为什么不能传入Integer
?
原因:擦拭法
如果我们传入的p
是Pair<Double>
,显然它满足参数定义Pair<? extends Number>
,然而,Pair<Double>
的setFirst()
显然无法接受Integer
类型。
这就是<? extends Number>
通配符的一个重要限制:方法参数签名setFirst(? extends Number)
无法传递任何Number
类型给setFirst(? extends Number)
。
即<? extends Number>类型的形参不能接受Number类型的实参
这里唯一的例外是可以给方法参数传入null
:
p.setFirst(null); // ok, 但是后面会抛出NullPointerException
p.getFirst().intValue(); // NullPointerException
即一句话总结:使用extends
通配符表示可以读,不能写,,上界<? extends T>不能往里存,只能往外取。
与extends相反
下界<? super T>不影响往里存,但往外取只能放在Object对象里
最后看一下什么是PECS(Producer Extends Consumer Super)原则,已经很好理解了:
原文:https://www.cnblogs.com/lorz5-blog/p/13546867.html