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