廖雪峰Java4反射与泛型-3范型-6super通配符

1.super通配符

1.1super通配符第一种用法

泛型的继承关系

Pair<Integer>不是Pair<Number>的子类,如
static void set(Pair<Integer> p, Integer first, Integer last){...}
set()不接受Pair<Number>
使用<? super Integer>使方法接收所有泛型类型为Integer或Integer超类的Pair类 
package com.testArray;

public class PairHepler {
    static void set(Pair<? super Integer> p,Integer first,Integer last){
        /**
         * 对Pair<? super Integer> 调用setFirst()方法:
         * 方法签名:void setFirst(? super Integer)
         * 可以安全传入Integer类型的变量:p.setFirst(new Integer(123))
         */
        p.setFirst(first);
        p.setLast(last);
    }
    static Integer add(Pair<? extends Number> p){
        /**
         * 对Pair<? super Integer>调用getFirst()方法:
         * 方法签名:? super Integer getFirst()
         * 无法赋值给Integer类型的变量。因为无法确定返回值就是Integer类型,可以确认其是Integer的超类,但无法确认就是Integer
         */
        Number first = p.getFirst();
        Number last = p.getLast();
        return first.intValue()+last.intValue();
    }
}
<? super Integer>的通配符:
*    允许调用set方法传入Integer的引用
*    不允许调用get方法获得Integer的引用
*    唯一例外:可以获取Object引用:Object o = p.getFirst();
    void process(List<? super Integer> list){...}

class List<T>{
    T.get(int index);//process方法不能调用
    void add(T t);//process方法可以调用
    void remove(T t);//process方法可以调用
}

1.2super通配符的第二种用法

<T super Integer>的通配符:
限定定义Pair<T>时只能是Integer或Integer的超类
public class Pair<T super Integer>{...}
Pair<Integer> ip = new Pair<>(1, 2);
Pair<Number> np = new Pair<>(1, 2);
Pair<String> sp = new Pair<>("a", "b");//error

2.extends和super的区别

方法参数为<? extends T>和方法参数为<? super T>的区别:
*    <? extends T>允许调用方法获取T的引用
*    <? super T>允许调用方法传入T的引用  
public class Collections{
    //把src的每个元素复制到dest中:List<? super T> dest目标,List<? extends T> src源文件
    public static <T> void copy(List<? super T> dest, List<? extends T> src){
        for(int i=0; i<src.size(); i++){
            T t = src.get(i);
            dest.add(t);
        }
    }
}

3.无限定通配符

public class Pair<T> {...}
public class PairHelper{
    static boolean isNull(Pair<?> p){
        return p.getFirst() == null || p.getLast() == null;
    }
}

<?>的通配符:
?号即包括了extends的限制,页包括了super的限制
不允许调用set方法,null除外
只能调用get方法获取Object的引用
因此使用Pair<?>只能获取Object的引用,以及是否为null 
Pair<?>和 Pair不同,通常情况下可以引入泛型参数<T>消除<?>通配符

Pair.java

package com.testArray;

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first,T last){
        this.first = first;
        this.last = last;
    }
    public void setFirst(T first){
        this.first = first;
    }
    public T getFirst() {
        return first;
    }
    public void setLast(T last){
        this.last = last;
    }
    public T getLast(){
        return last;
    }
    public String toString(){
        return "Pair(" + first+", "+last+")";
    }
}

Main.java

package com.testArray;

public class Main {
    public static void main(String[] args){
        Pair<Integer> p = new Pair<>(0, 0);
        System.out.println(p);
        set(p, 123, 456);
        System.out.println(p);
        Pair<Number> n = new Pair<>(1.2,3.4);
        System.out.println(n);
        set(n,99,88);
        System.out.println(n);
    }
    static void set(Pair<? super Integer> p, Integer first,Integer last){
        p.setFirst(first);
        p.setLast(last);
        //Integer f = p.getFirst();
    }
}

4.总结:

使用类似<? super Integer>通配符作为方法参数时表示:
*    方法内部可以调用传入Integer引用的方法:obj.setXXX(Integer n)
*    方法内部无法调用获取Integer引用的方法(Object除外)Integer n = obj.getXxx()
使用类似<T super Integer>定义泛型类时表示:
*    泛型类型限定为Integer或Integer的超类
无限定通配符<?>很少使用,可以用<T>替换
原文地址:https://www.cnblogs.com/csj2018/p/10426465.html