关于Java协变性的思考
简而言之,如果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协变性的思考的更多相关文章
- Java 8 CompletableFuture思考
Java 8 CompletableFuture思考 最近一直在用响应式编程写Java代码,用的框架大概上有WebFlux(Spring).R2dbc.Akka...一些响应式的框架. 全都是Java ...
- 关于Java 项目的思考总结
Java 项目思考总结 前言 今天是2017年3月25日,笔者已经毕业半年,工作经验一年. 正好有心思写这个总结. 持续开发 对于Java项目,我所接触的一般就是JavaWeb项目和 Java Jar ...
- Java框架的思考
目前的JAVA 企业级开发框架,我们常用的大致包括IOC AOP MVC ORM框架 1. IOC spring是一个非常棒的ico容器,其思想非常简单,用一个集合对象如MAP 来缓存对象(对象都是单 ...
- 关于java对象的思考
不可变对象和类 由不可变类创建的对象就是不可变对象,要使一个类成为不可变的,它必须满足下面的需求: 所有数据域都是私有的 没有修改器方法 没有一个访问器的方法,它会返回一个指向可变数据域的引用 看下面 ...
- 对 Kotlin 与 Java 编程语言的思考
从长远来看,排名前10的也基本上是Java.C.C++.Python.C#.VB.PHP.JavaScript.至于Kotlin的排名,11月份在编程语言仅排41名,Ratings仅有0.216%. ...
- 有 a - b < c 对Java安全性的思考
软件工程中,不论使用哪种开发语言,安全性一直是一个非常棘手却又重要的问题.安全性是软件开发领域永远的主题之一,而且随着互联网的蜂拥发展而带动的新技术的兴起与革命(比如近几年火起来的node.js,py ...
- 关于java异常处理的思考
学习java的过程中,初学者更多的是为了实验而写代码,而不考虑实际情况中的人机交互过程中的一些问题. 在java项目中,更多的用户不会因为你给了某些限制提醒,他就一定会按照你所给的提示来输入或者操作, ...
- JAVA设计方法思考之如何实现一个方法执行完毕后自动执行下一个方法
今天编程时,突然想起来在一些异步操作或Android原生库的时候,需要我们实现一些方法, 这些方法只需要我们具体实现,然后他们会在适当的时候,自动被调用! 例如AsyncTask,执行玩doInBac ...
- java权限设计思考
1.粗粒度权限设计与细粒度权限设计 粗粒度(Coarse-graind) 表示类别级,即仅考虑对象的类别(the type of object),不考 ...
随机推荐
- Java - PhantomJS + EChartsConvert实现ECharts图片保存到服务端
1.所需工具 1>phantomjs:官网下载http://phantomjs.org/download.html 国内镜像http://npm.taobao.org/dist/phantomj ...
- Python入门之format()方法
在此列出format()方法的一些基本使用: >>> '{}{}{}'.format('圆周率是',3.1415926,'...') '圆周率是3.1415926...' >& ...
- 洛谷 P1484 种树(优先队列,贪心,链表)
传送门 解题思路 第一眼的贪心策略:每次都选最大的. 但是——不正确! 因为选了第i个树,第i-1和i-1棵树就不能选了.所以,要有一个反悔操作. 选了第i个后,我们就把a[i]的值更新为a[l[i] ...
- 【JZOJ 3910】Idiot 的间谍网络
题面: Description 作为一名高级特工,Idiot 苦心经营多年,终于在敌国建立起一张共有n 名特工的庞大间谍网络. 当然,出于保密性的要求,间谍网络中的每名特工最多只会有一名直接领导.现在 ...
- [LeetCode] 39. 组合总和
题目链接 : https://leetcode-cn.com/problems/combination-sum/ 题目描述: 给定一个无重复元素的数组 candidates 和一个目标数 target ...
- 初学Git——命令总结
首先,感谢廖雪峰老师制作的Git教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b0 ...
- Comet OJ - Contest #0 A题 解方程 (数学)
题目描述 小象同学在初等教育时期遇到了一个复杂的数学题,题目是这样的: 给定自然数 nn,确定关于 x, y, zx,y,z 的不定方程 \displaystyle \sqrt{x - \sqrt{n ...
- C#基础知识之父子类,实例、静态成员变量,构造函数的执行顺序(经典示例)
父子类.示例.静态成员变量.构造函数的概念的基础理解完全可以利用下面的示例诠释,非常经典,直接上代码: public class ShowInfo { public ShowInfo(string i ...
- 3--面试总结-es6
es6文档:http://es6.ruanyifeng.com/1.es6新特性 let/const 变量的解构赋值(数组的解构赋值,对象的解构赋值,字符串的解构赋值,数值和布尔值的解构赋值,函数参数 ...
- SQL查询优化的步骤
一.定位慢查询 SQL优化的一般步骤:先查询mysql数据库运行状况,然后定位慢查询,再分析sql的执行过程,然后进行优化 1.使用show status查询数据库的运行状况 //显示数据库运行状态 ...