逆变与协变

本贴最后更新于 1950 天前,其中的信息可能已经时移世易
Java 中的逆变与协变
Number num=new Integer(1);
ArrayList<Number> list=new ArrayList<Integer>(); //type mismatch
List<? extends Number> list1=new ArrayList<Number>();
list1.add(new Integer(1)); //error
list1.add(new Float(1.2f)); //error
  1. 里氏替换原则

所有引用父类的地方必须能透明的使用其子类对象

  • 包含以下四层含义:

    • 子类完全拥有父类的方法,且具体子类必须实现父类的抽象方法
    • 子类可以增加自己的方法
    • 当子类覆盖或者实现父类的方法时,方法的形参要比父类更为宽松
    • 当子类覆盖或者实现父类的方法时,方法的返回值要比父类更严格
    // 根据里氏替换原则,我们在实例对象时,可以使用其子类进行实例化
    // 左侧需要的是Number 类型的对象,可以使用Integer子类
    Number num=new Integer(1);
    
  1. 逆变与协变定义

    逆变与协变用来描述类型转换后的继承关系,其定义:

    如果 A、B 表示类型, f(.) 表示类型转换,< 表示继承关系(比如 A<B, 表示 A 是 B 的子类)

    • 当 f(.)是 逆变 时,如果 A<B,那么 f(B)<f(A)
    • 当 f(.)是 协变 时,如果 A<B,那么 f(A)<f(B)
    • 当 f(.)是 不变 时,如果 A<B,那么上述两个式子都不成立。即 f(A)和 f(B)没有继承关系
    // 数组是协变的  :令f(A)=[]A,有
    // Integer[]数组可以使用Number[]接收,即Number[]的引用可以使用Integer[]对象
    // 所以 Integer[] < Number[] ,Integer[]是Number[]的子类
    Number[] numbers=new Integer[3]; 
    // 泛型是不变的  :令f(A)=ArrayList<A>()
    // ArrayList<Number> 不能接收ArrayList<Integer> ,反之也不行,则俩者之间没有继承关系
    // 所以泛型是不变的
    ArrayList<Number> numList=new ArrayList<Integer>(); //error
    ArrayList<Integer> intList=new ArrayList<Number>(); //error
    // 方法调用: 当调用方法result=method(n);
    // 传入的形参n可以替换为n的子类型,即f(method(n的子类)) > f(method(n)),传入形参是逆变
    // 返回值可以替换为method返回值的父类型 所以f(result父类)>f(result),所以方法返回值是协变
    public static Number method(Number num){
        return 1;
    }
    Object result=method(new Integer(1)); //correct
    Number numResult=method(new Object()); //error
    Integer result=method(new Integer(2)); //error
    // 方法重写: 
    // java1.5开始,子类覆盖父类方法时,允许返回更为具体的类型()
    // Sub<Super ,返回值 Sub的返回值< Super的返回值,协变
    // 方法的形参必须和父类保持一致(不变)
    class Super{
        public abstract Number method(Number n)
    }
    class Sub extends Super{
        @Override
        public Integer method(NUmber n){ ... }
    }
    
  2. 总结

    1. 子类重写父类的方法时,形参类型必须一致,而返回值可以 返回 更具体的类型
    2. java 的泛型必须一致,数组可以使用
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    324 引用 • 1395 回帖 • 1 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    69 引用 • 190 回帖 • 491 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖 • 32 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 247 回帖 • 168 关注
  • gRpc
    10 引用 • 8 回帖 • 54 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    40 引用 • 40 回帖
  • danl
    74 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 23 关注
  • 博客

    记录并分享人生的经历。

    270 引用 • 2386 回帖
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • 音乐

    你听到信仰的声音了么?

    59 引用 • 509 回帖
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    20 引用 • 245 回帖 • 235 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 37 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 510 关注
  • 安全

    安全永远都不是一个小问题。

    189 引用 • 813 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    261 引用 • 662 回帖
  • Sillot

    Sillot (汐洛)孵化自思源笔记,致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点
    Github 地址:https://github.com/Hi-Windom/Sillot

    20 引用 • 6 回帖 • 31 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 38 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 691 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    21 引用 • 37 回帖 • 509 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    5 引用 • 15 回帖 • 217 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    14 引用 • 7 回帖
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 24 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    492 引用 • 1383 回帖 • 366 关注