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

参考:

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 {
}

猜你喜欢

转载自www.cnblogs.com/tigerlion/p/10659515.html
今日推荐