关于逆变和协变的一些理解

 

Person 是个中间的类,上面有父类 Bean,下面有子类 Student。

对于传入数据

当用 extends 定义了上界时,就不是再传入 Person 的父类了,只能传入自身或子类,而且(如果是定义容器,如 List<? extends Fruit>)只能是只读形式,不能添加。这是因为父类 Bean 中可能没有 Person 中定义的方法,如果可以传入并调用的话,会出错。只读是因为如果可以添加的话,那么在传递的过程中,就可以把原先传入的子类改为其它子类,那么类型就会错乱,比如原先的子类A中只有 read 方法,在方法中替换成其它只有 write 方法的子类B,当列表返回再调用 read 方法时就会导致代码出错,所以系统才会把定了上界的类型设置为只读。

(当使用了泛型的通配符之后,确实可以实现将ArrayList进行向上转型了,实现了泛型的协变,但是却再也不能往容器中放任何东西了,连Apple本身都被禁止了。因为,在定义了fruitList之后,编译器只知道容器中的类型是Fruit或者它的子类,但是具体什么类型却不知道,编译器不知道能不能比配上就都不允许比配了。类比数组,在编译器的时候数组允许向数组中放Fruit和Orange等非法类型,但是运行时还是会报错,泛型是将这种检查移到了编译期,协变的过程中丢失了类型信息。)

当用 super 定义了下界时,就不是再传入 Person 的子类了,只能传入自身或父类,而且(如果是定义容器,如 List<? super Fruit>)可以添加(自身及子类,确定是子类)。这是为了添加需要,如果可以传入子类的话,比如子类A的列表,这时再往里面加入子类B的话,就会出错,但如果是父类的话,就没有问题。

(可以看到使用super就可以实现泛型的逆变,使用super的时候指出了泛型的下界是Apple,可以接受Apple的父类型,既然是Apple的父类型,编辑器就知道了向其中添加Apple或者Apple的子类是安全的了,所以,此时可以向容器中进行存,但是取的时候编辑器只知道是Apple的父类型,具体什么类型还是不知道,所以只有取值会出现编译错误,除非是取Object类型。)

JAVA中的协变与逆变 - 司霖 - 博客园

对于取数据

当用 extends 定义了上界时,取数据是安全的,因为父类有了上界,用父类的类型即可。

当用 super 定义了下界时,取数据是不安全的,因为不知道传进去的具体类型是什么,取出来了也不确定对象中有没有想调用的方法,所以不安全。

通配符上限,取出安全,传入不可靠。

通配符下限,传入安全,取出不可靠。

  • 要从泛型类取数据时,用extends;
  • 要往泛型类写数据时,用super;
  • 既要取又要写,就不用通配符(即extends与super都不用)。

Java泛型中的PECS原则

Java泛型中的PECS原则_薛瑄的博客-CSDN博客_pecs原则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值