栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

每天记录学习的新知识 :Java中的协变和逆变

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

每天记录学习的新知识 :Java中的协变和逆变

协变和逆变
  • 什么是协变和逆变
  • 什么情况下存在协变和逆变
    • 数组是协变的
    • 泛型是不变的?
    • 协变的实现
    • 逆变的实现
  • 参考地址

什么是协变和逆变

Java中String类型是继承自Object的,姑且记做String ≦ Object,表示String是Object的子类型,String的对象可以赋给Object的对象。而Object的数组类型Object[],理解成是由Object构造出来的一种新的类型,可以认为是一种构造类型,记f(Object)。

那么可以这么来描述协变和逆变:
当A ≦ B时,如果有f(A) ≦ f(B),那么f叫做协变;
当A ≦ B时,如果有f(B) ≦ f(A),那么f叫做逆变;
如果上面两种关系都不成立则叫做不可变。

什么情况下存在协变和逆变 数组是协变的
    public class A {
    }

    public class B extends A {
    }
        A a = new B();

        A[] as = new A[10];
        as[0] = new B();
泛型是不变的?

不设置通配符的情况下,

ArrayList list = new ArrayList();
 

无法编译。

原因是类型擦除的存在,最终都会编译成Object,所以不支持协变。

但是,如果配置通配符,就可以实现逆变和协变,这是因为编译后也不会都是Object,而是我们定的限定类型。

协变的实现

协变通过 ?extends 实现,指定父类类型。

协变只读:
数据一旦创建禁止修改,这是因为他也不知道你第一次创建的时候,是使用了什么子类类型,第二次再修改和第一次的类型不一致肯定会导致问题,这就是不能改的原因。

		Number number = new Integer("1");//子可以赋值给父
        //协变
        ArrayList< ? extends  Number> list= new ArrayList();//子可以赋值给父
        list.add(1); //error 
        Number number =  list.get(1);
逆变的实现

逆变通过 ?super 实现,指定子类类型。

逆变只写:因为Number是Integer父类,指定子类的情况下,只要是父类都可以写入;但是如果取出来,就不知道取出后应该是什么父类类型了,这就是不能取的原因

		Number number = new Integer("1");//子可以赋值给父
        //逆变
        ArrayList< ? super Integer> list2 = new ArrayList();//父可以赋值给子
        list2.add(1);
        Integer integer = list2.get(1);//error

参考地址

Java中的逆变与协变:https://blog.csdn.net/zero__007/article/details/52245475

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号