如何使用泛型(四)-super

如何使用泛型(四)-super 如果你有一個類別是這樣
內部有一個方法用來傳入一個陣列並且把該陣列的資訊名稱印出來。
class ListName{
    public static <T> void runList(List<? super T> list){
        list.stream().forEach(x-> System.out.println(x.toString()));
    }
}
現在有一個類別使用了這個方法
class Obj<T>{
    public void run(List<? super T> list){
        ListName.runList(list);
    }
}

class A extends ListName{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
}
class B extends ListName{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
}
你會發現只要這樣呼叫,
他都可以正確找到對應的類別資訊
A a1 = new A();
a1.setName("a1");
A a2 = new A();
a2.setName("a2");
B b1 = new B();
b1.setName("b1");
B b2 = new B();
b2.setName("b2");

List<ListName> list = new ArrayList<>();
list.add(a1);
list.add(a2);
list.add(b1);
list.add(b2);

Obj<A> o1 = new Obj<>();
o1.run(list);
結果如下
a1
a2
b1
b2
< ? super T>的定義就是從該型態到它最初的T類別, 都會視為同一種型態。
白話一點就是如果你是某家族, 就可以使用。
< ? extends T>的定義就是只能限定繼承T類別以下的型態。
白話一點就是你必須是某人或它兒子才可以使用。
所以當你把下面程式碼改成extends就會發現編譯不了
class Obj<T>{
    public void run(List<? extends T> list){
        ListName.runList(list);
    }
}
//...
Obj<A> o1 = new Obj<>();
o1.run(list);//無法編譯
原因就出在Obj只是允許T的型態,
也就是說 當你宣告T為A型態的時候,
所以run方法只允許A類別或A的子類別存取。