1. 程式人生 > >再論<? extends T>和<? super T>

再論<? extends T>和<? super T>

ati 知乎 abstract array http lean rand int https

參考:

https://www.cnblogs.com/drizzlewithwind/p/6100164.html

Java 泛型 <? super T> 中 super 怎麽 理解?與 extends 有何不同? - 胖君的回答 - 知乎
https://www.zhihu.com/question/20400700/answer/117464182

說得很清楚,但是有一處沒說明白(知乎上有人提出來了):

使用<? super Fruit>時,子類類型也接受:

        Plate<? super Fruit> p2 = new Plate<>(new Fruit());
        p2 = new Plate<>(new Food());
        p2 = new Plate<>(new Fruit());
        p2 = new Plate<>(new Apple()); // 這是個子類型

新寫一版,不引入Plate類,直接用JAVA自己的ArrayList類來做測試。

public interface List<E> extends Collection<E> {
    ...
    boolean add(E e);
    ...
    E get(int index);
    ....
}
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{...}

定義三個類,Fruit->Apple->RedApple,聲明ArrayList,有如下現象:

import java.util.*;
public class 泛型_通配符邊界2 {
    public static void main(String[] args) {
        ArrayList<Apple> p1 = new ArrayList<Apple>();
        // 【震驚!裝得了蘋果,裝不了紅蘋果】
        // ↓Type mismatch:
        // cannot convert from ArrayList<RedApple> to ArrayList<Apple>
        // ArrayList<Apple> p2 = new ArrayList<RedApple>();
    }
}
class Fruit {
}
class Apple extends Fruit {
}
class RedApple extends Apple {
}

解決方案就是

【1.<? extends Fruit>,定類型繼承關系的上界】
【2.<? super Apple>,確定類型繼承關系的下界】

解決方案如下,照著註釋看便是

package ah;
import java.util.*;
public class 泛型_通配符邊界2 {
    public static void main(String[] args) {
        ArrayList<Apple> p1 = new ArrayList<Apple>();
        // 【震驚!裝得了蘋果,裝不了紅蘋果】
        // ↓Type mismatch:
        // cannot convert from ArrayList<RedApple> to ArrayList<Apple>
        // ArrayList<Apple> p2 = new ArrayList<RedApple>();
        // 【1.<? extends Fruit>,定類型繼承關系的上界:】
        // 能裝Apple以及一切Apple的派生類
        ArrayList<? extends Apple> p3 = new ArrayList<Apple>();
        p3 = new ArrayList<RedApple>();
        // ↓上層的類不接受
        // Type mismatch:
        // cannot convert from ArrayList<Fruit> to ArrayList<? extends Apple>
        // p3 = new ArrayList<Fruit>();
        // 【然而,extends是只讀的,不能寫入】
        // p3.add(new Apple());
        if (p3.size() != 0) {
            Apple apple = p3.get(0);
        }
        // 【2.<? super Apple>,確定類型繼承關系的下界】
        // 能裝水果以及一切水果的基類
        ArrayList<? super Apple> p4 = new ArrayList<Apple>();
        p4 = new ArrayList<Fruit>();
        p4 = new ArrayList<Apple>();
        // Type mismatch:
        // cannot convert from ArrayList<RedApple> to ArrayList<? super Apple>
        // p4 = new ArrayList<RedApple>();
        // 【可讀可寫,讀出來的是Object類型】
        p4.add(new RedApple());// 子類對象但是可以寫進入,因為默認向上轉型
        Object object = p4.get(0);
        System.out.println(object);
        // 最後,JDK 7之後,ArrayList後面的<>裏什麽都不用寫
        List<Apple> p2 = new ArrayList<>();
    }
}
class Fruit {
}
class Apple extends Fruit {
}
class RedApple extends Apple {
}

再論<? extends T>和<? super T>