简而言之,如果A IS-A B,那么A[] IS-A B[]。
举例:现在有类型Person、Employee和Student。Employee
是一个(IS-A) Person,Student是一个(IS-A)Person。那么下面的语句可以通过编译:

但是上面的代码在运行时却会出错。因为arr[0]实际上是引用一个Employee,可是Student IS-NOT-A
Employee。这样就产生了混乱。这种错误正是由于Java数组的协变性而产生的。那么Java为什么不禁止数组协变呢?因为SE5之前还没有泛型,但很多代码迫切需要泛型来解决问题。

例如Arrays.equals()方法的底层实现调用的是Object.equals()方法,和数组中元素的具体类型无关,这充分利用了Java中任何类型都继承自Object类的特性,避免了为每个类型都重新定义Arrays.equals()方法。而在没有泛型的时代,要让Object[]能接受所有数组类型,最简单的办法就是让数组接受协变,把String[],Integer[]都定义成Object[]的派生类,如何自学英语然后多态就起作用了。

这是基于数组的一个独有特性:

数组记得它内部元素的具体类型,并且会在运行时做类型检查。

因为arr[0]记得它内部的元素类型是Employee,所以运行时给它插入一个Student类型会报错。

这个特性使得Java数组协变带来的影响不会酿成大错——错误最终还是会被检测出来,只不过是从编译时推迟到了运行时。

正是有这个特性,Java当初才敢于把数组设计成协变的。虽然向上转型以后,编译期类型检查放松了,但因为数组运行时对内部元素类型的严格检查,不匹配的类型还是插不进去的。这也是为什么容器Collection不能设计成协变的原因——Collection不做运行时类型检查。

Java容器因为不具有协变性,因而少了灵活性。因此,在Java5中,Java通过通配符和泛型对容器进行了弥补。

关于Java协变性的思考的更多相关文章

  1. Java 8 CompletableFuture思考

    Java 8 CompletableFuture思考 最近一直在用响应式编程写Java代码,用的框架大概上有WebFlux(Spring).R2dbc.Akka...一些响应式的框架. 全都是Java ...

  2. 关于Java 项目的思考总结

    Java 项目思考总结 前言 今天是2017年3月25日,笔者已经毕业半年,工作经验一年. 正好有心思写这个总结. 持续开发 对于Java项目,我所接触的一般就是JavaWeb项目和 Java Jar ...

  3. Java框架的思考

    目前的JAVA 企业级开发框架,我们常用的大致包括IOC AOP MVC ORM框架 1. IOC spring是一个非常棒的ico容器,其思想非常简单,用一个集合对象如MAP 来缓存对象(对象都是单 ...

  4. 关于java对象的思考

    不可变对象和类 由不可变类创建的对象就是不可变对象,要使一个类成为不可变的,它必须满足下面的需求: 所有数据域都是私有的 没有修改器方法 没有一个访问器的方法,它会返回一个指向可变数据域的引用 看下面 ...

  5. 对 Kotlin 与 Java 编程语言的思考

    从长远来看,排名前10的也基本上是Java.C.C++.Python.C#.VB.PHP.JavaScript.至于Kotlin的排名,11月份在编程语言仅排41名,Ratings仅有0.216%. ...

  6. 有 a - b < c 对Java安全性的思考

    软件工程中,不论使用哪种开发语言,安全性一直是一个非常棘手却又重要的问题.安全性是软件开发领域永远的主题之一,而且随着互联网的蜂拥发展而带动的新技术的兴起与革命(比如近几年火起来的node.js,py ...

  7. 关于java异常处理的思考

    学习java的过程中,初学者更多的是为了实验而写代码,而不考虑实际情况中的人机交互过程中的一些问题. 在java项目中,更多的用户不会因为你给了某些限制提醒,他就一定会按照你所给的提示来输入或者操作, ...

  8. JAVA设计方法思考之如何实现一个方法执行完毕后自动执行下一个方法

    今天编程时,突然想起来在一些异步操作或Android原生库的时候,需要我们实现一些方法, 这些方法只需要我们具体实现,然后他们会在适当的时候,自动被调用! 例如AsyncTask,执行玩doInBac ...

  9. java权限设计思考

    1.粗粒度权限设计与细粒度权限设计             粗粒度(Coarse-graind)        表示类别级,即仅考虑对象的类别(the   type   of   object),不考 ...

随机推荐

  1. PHP 经典有趣的算法

    原文:https://blog.csdn.net/a519395243/article/details/77942913 1.一群猴子排成一圈,按1,2,…,n依次编号.然后从第1只开始数,数到第m只 ...

  2. python学习第五十二天logging模块的使用

    很多程序都有记录日志的需求,并且日志包含的信息即有正常的程序访问日志,还可能有错误,警告等信息输出,python的 logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,loggin ...

  3. 小程序之如和使用view内部组件来进行页面的排版功能

    这篇文章主要介绍了关于小程序之如和使用view内部组件来进行页面的排版功能,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 涉及知识点: 1.垂直排列,水平排列 2.居中对齐 示例: 1 ...

  4. git合并丢失代码问题分析与解决(错误操作导致)

    问题描述 我们在主干dev和branch1分支上进行并行开发.当要把branch1功能的代码合并到dev上时,发现dev上开发的部分功能代码找不到了. 那么,是在branch1上,作了删除提交导致的吗 ...

  5. 42. Trapping Rain Water (JAVA)

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  6. GROUP BY关键字优化

    1.group by实质是先排序后进行分组,遵照索引建的最佳左前缀 2.当无法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置 ...

  7. Spring基础14——Bean的生命周期

    1.IOC容器中的Bean的生命周期方法 SpringIOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务.SpringIOC容器对Bean的生命周期进行管理 ...

  8. 管线命令(Pipe)

    管线命令接受|前面传来的stdout,管线示意图如下所示: 管线两个需要注意的地方: 1.管线仅会处理stdout,忽略对stderr的处理 2.管线必须接受前个指令的stdin才是 那么,如果我想接 ...

  9. 【转】内核中的内存申请:kmalloc、vmalloc、kzalloc、kcalloc、get_free_pages

    转自:https://www.cnblogs.com/yfz0/p/5829443.html 在内核模块中申请分配内存需要使用内核中的专用API:kmalloc.vmalloc.kzalloc.kca ...

  10. 005-sort 命令使用

    字符处理命令 sort 排序命令 排序选项: -f, --ignore-case 忽略字母大小写 -n, --numeric-sort 根据字符串数值比较 -r, --reverse 逆序输出排序结果 ...