JAVA 协变、逆变、泛型,extends,super

简单例子

//苹果Apple
public class Apple extends Fruit {

}
//香蕉Banana
public class Banana extends Fruit {

}

//动物Animal
public interface Animal {
public void eat(Fruit fruit);
public void eat(List< Fruit > fruits);
public void eat(List<? extends Fruit > fruits);
}

//猴子Monkey
public class Monkey{
public void eat(Fruit fruit){

}
public void eatFruits(List< Fruit > fruits){

}
public void eatFruitsCovariant(List<? extends Fruit > fruits){

}
}


关于Monkey,
Monkey monkey = new Monkey();
//1.可以正常编译
monkey.eat(new Apple ());

//2.可以正常编译
Apple apple = new Apple();
Banana banana = new Banana();
List fruits = new ArrayList<>();
fruits.add(apple);
fruits.add(banana);
monkey.eatFruits(fruits);

//3.可以正常编译
Apple apple = new Apple();
Apple apple1 = new Apple();
List< Apple > fruits = new ArrayList<>();
fruits.add(apple);
fruits.add(apple1);
monkey.eatFruitsCovariant(fruits);

//4.不可以正常编译
Apple apple = new Apple();
Apple apple1 = new Apple();
List< Apple > fruits = new ArrayList<>();
fruits.add(apple);
fruits.add(apple1);
monkey.eatFruits(fruits);
//编辑器提示类型错在这里插入图片描述
前面三种情况都好理解,第四种情况为什么不行?
协变:把List< Apple >赋值给List< Fruit >即协变,具体概念可百度查询,在java中是不支持这种写法的。

试想一下,我有个
List< Apple > apples = new ArrayList<>();
//放两个苹果
apples.add(new Apple());
apples.add(new Apple());
//此时假如java支持
List< Fruitt > fruits = apples;
//然后,再放入一个香蕉。List变量允许放入Banana的,上面的第二种情况。
fruits.add(new Banana());
//这时候如果对原来的apples操作,取出第三个,则会导致类型转换异常.
//因为第三个是Banana而不是Apple。
Apple apple3 = apples. apples.get(2);
//所以不允许把List< Apple>赋值给List< Fruit >是有必要的。


但是这样就带来一个问题,即对于Monkey我们额外需要加入
public void eatApples(List< Apple> apples){

}
public void eatBananas(List< Banana> bannas){

}
显然这是不可接受的,因此我们需要让协变List< Fruit > fruits = apples 生效。
这里java泛型提供了一种写法,即
//这表示这个List里存放的是Fruit或其子类。
List<? extends Fruit> fruits = apples;
这让协变得以允许,但是考虑到我们前面分析的可能的类型转换异常。java里规定,协变后只可读,不可以修改。并且,由于List里存放的都是Fruit或其子类,我们并不清楚任意一个元素具体是什么类型。因此使用的时候,我们需要用Fruit变量来承接。
Fruit fruit = fruits.get(0);

//逆变,后面再写了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值