关于泛型的通配符一些补充

关于泛型通配符的一些补充

extends通配符

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

原因:擦拭法

如果我们传入的pPair<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>不能往里存,只能往外取。


super通配符

与extends相反

下界<? super T>不影响往里存,但往外取只能放在Object对象里


PECS原则

最后看一下什么是PECS(Producer Extends Consumer Super)原则,已经很好理解了:

  • 频繁往外读取内容的,适合用上界Extends。
  • 经常往里插入的,适合用下界Super。
posted @ 2020-08-22 19:48  lorz5  阅读(91)  评论(0)    收藏  举报