Java 逆变 协变

2022-03-15  本文已影响0人  zhengaoly

List <? extend Number> xiebianList= new ArrayList<Integer>();

表示xiebianList这个变量可以=Number的任何子类的List,例如这里可以等于Integer的ArrayList

但是往里面添加的时候,由于Number子类不确定,所以如果添加一个Float,此时就相当于往ArrayList<Integer>里添加一个Float,而ArrayList<Integer>.add(e)要求的类型e是Integer的,显然是不合理的。所以不能对协变进行修改操作。

但是获取是没问题的,因为获取的对象都是Number的子类

List<? super Number>nibianList = new ArrayList<Number>();

表示nibianList 这个变量可以=Number的任何父类的List,例如这里可以等于Number的ArrayList,也可以等于Number父类的ArrayList,如new ArrayList<Object>()

这里王nibianList添加元素时,如果添加Number的父类,如nibianList.add(new Object());那就不合理了,因为此时nibianList.add要求参数是Number的,但是添加的确实一个object对象,相当于父类做了实参。显然是不合理的。

如果添加Number的子类,是合理的,因为Number的父类,显然也是Number子类的父类,那么add方法的参数,实际上是子类做实参,是没有问题的。

class Fruit{

}
class Apple extends Fruit{

}

class PearApple extends Apple{

}

public class TestNibianxiebian {
    public static void main(String[] args) {
        List<Apple> apples = new ArrayList<>();
        List<Fruit> fruits = new ArrayList<>();
        List<PearApple> pearApples = new ArrayList<>();
        fruits.add(new Apple());
        fruits.add(new PearApple());

        List<? extends Fruit> xiebian = apples;//只读
        xiebian = pearApples;

        List<? super Apple> nibian = fruits;//可以等于apple及apple的父类
        nibian = apples;//apple的父类容器都是合法的
        nibian.add(new PearApple());//可以添加apple及子类对象
        nibian.add(new Apple());
        //nibian这个变量=父类的容器,也就是add的形参是apple或者apple的父类,添加父类的不合法的,但是添加apple的子类是合法的,因为子类实参赋值给父类是类型安全的转换
//        nibian.add(new Fruit());
    }
    public void test1(List<? extends Number> data){

    }
    public void test(List<? super Number> data){

    }
}
上一篇下一篇

猜你喜欢

热点阅读