01、 多态是什么

在我刻板的印象里,西游记里的那段孙悟空和二郎神的精彩对战就能很好的解释“多态”这个词:一个孙悟空,能七十二变;一个二郎神,也能七十二变;他们都可以变成不同的形态,但只需要悄悄地喊一声“变”。

Java的多态是什么呢?其实就是一种能力——同一个行为具有不同的表现形式;换句话说就是,执行一段代码,Java 在运行时能根据对象的不同产生不同的结果。和孙悟空和二郎神都只需要喊一声“变”,然后就变了,并且每次变得还不一样;一个道理。

多态的前提条件有三个:

  • 子类继承父类
  • 子类覆盖父类的方法
  • 父类引用指向子类对象

多态的一个简单应用,来看程序清单1-1:

//子类继承父类
public class Wangxiaoer extends Wanger {public void write() { // 子类覆盖父类方法System.out.println("记住仇恨,表明我们要奋发图强的心智");}public static void main(String[] args) {// 父类引用指向子类对象Wanger[] wangers = { new Wanger(), new Wangxiaoer() };for (Wanger wanger : wangers) {// 对象是王二的时候输出:勿忘国耻// 对象是王小二的时候输出:记住仇恨,表明我们要奋发图强的心智wanger.write();}}
}class Wanger {public void write() {System.out.println("勿忘国耻");}
}

02、 多态与后期绑定

现在,我们来思考一个问题:程序清单1-1在执行 wanger.write() 时,由于编译器只有一个 Wanger 引用,它怎么知道究竟该调用父类 Wanger 的 write() 方法,还是子类 Wangxiaoer 的 write() 方法呢?

答案是在运行时根据对象的类型进行后期绑定,编译器在编译阶段并不知道对象的类型,但是Java的方法调用机制能找到正确的方法体,然后执行出正确的结果。

多态机制提供的一个重要的好处程序具有良好的扩展性。来看程序清单2-1:

//子类继承父类
public class Wangxiaoer extends Wanger {public void write() { // 子类覆盖父类方法System.out.println("记住仇恨,表明我们要奋发图强的心智");}public void eat() {System.out.println("我不喜欢读书,我就喜欢吃");}public static void main(String[] args) {// 父类引用指向子类对象Wanger[] wangers = { new Wanger(), new Wangxiaoer() };for (Wanger wanger : wangers) {// 对象是王二的时候输出:勿忘国耻// 对象是王小二的时候输出:记住仇恨,表明我们要奋发图强的心智wanger.write();}}
}class Wanger {public void write() {System.out.println("勿忘国耻");}public void read() {System.out.println("每周读一本好书");}
}

在程序清单 2-1 中,我们在 Wanger 类中增加了 read() 方法,在 Wangxiaoer 类中增加了eat()方法,但这丝毫不会影响到 write() 方法的调用。write() 方法忽略了周围代码发生的变化,依然正常运行。这让我想起了金庸《倚天屠龙记》里九阳真经的口诀:“他强由他强,清风拂山岗;他横由他横,明月照大江。”

多态的这个优秀的特性,让我们在修改代码的时候不必过于紧张,因为多态是一项让程序员“将改变的与未改变的分离开来”的重要特性。

03、 多态与构造器

在构造器中调用多态方法,会产生一个奇妙的结果,我们来看程序清单3-1:

public class Wangxiaosan extends Wangsan {private int age = 3;public Wangxiaosan(int age) {this.age = age;System.out.println("王小三的年龄:" + this.age);}public void write() { // 子类覆盖父类方法System.out.println("我小三上幼儿园的年龄是:" + this.age);}public static void main(String[] args) {new Wangxiaosan(4);
//      上幼儿园之前
//      我小三上幼儿园的年龄是:0
//      上幼儿园之后
//      王小三的年龄:4}
}class Wangsan {Wangsan () {System.out.println("上幼儿园之前");write();System.out.println("上幼儿园之后");}public void write() {System.out.println("老子上幼儿园的年龄是3岁半");}
}

从输出结果上看,是不是有点诧异?明明在创建 Wangxiaosan 对象的时候,年龄传递的是 4,但输出结果既不是“老子上幼儿园的年龄是 3 岁半”,也不是“我小三上幼儿园的年龄是:4”。

为什么?

因为在创建子类对象时,会先去调用父类的构造器,而父类构造器中又调用了被子类覆盖的多态方法,由于父类并不清楚子类对象中的属性值是什么,于是把int类型的属性暂时初始化为 0,然后再调用子类的构造器(子类构造器知道王小二的年龄是 4)。

04、 多态与向下转型

向下转型是指将父类引用强转为子类类型;这是不安全的,因为有的时候,父类引用指向的是父类对象,向下转型就会抛出 ClassCastException,表示类型转换失败;但如果父类引用指向的是子类对象,那么向下转型就是成功的。

来看程序清单4-1:

public class Wangxiaosi extends Wangsi {public void write() {System.out.println("记住仇恨,表明我们要奋发图强的心智");}public void eat() {System.out.println("我不喜欢读书,我就喜欢吃");}public static void main(String[] args) {Wangsi[] wangsis = { new Wangsi(), new Wangxiaosi() };// wangsis[1]能够向下转型((Wangxiaosi) wangsis[1]).write();// wangsis[0]不能向下转型((Wangxiaosi)wangsis[0]).write();}
}class Wangsi {public void write() {System.out.println("勿忘国耻");}public void read() {System.out.println("每周读一本好书");}
}

05、总结

我喜欢把复杂的事情尽量简单化,把简单的事情有趣化——多态是 Java 的三大特性之一,它本来需要长篇大论的介绍,但我觉得实在没有必要,把关键的知识点提炼出来就足够了。更重要的是,你要通过实践去感知多态的优秀之处。

chenssy 大佬对多态下了一个非常经典的结论,我们不妨大声的朗读几遍:

多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时并不确定,而是在程序运行期间才确定;即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。


上一篇:Java代码复用的三种常用方式:继承、组合和代理

下一篇:Java 抽象类和接口,看这一篇就够了

微信搜索「沉默王二」公众号,关注后回复「免费视频」获取 500G Java 高质量教学视频(已分门别类)。

Java:多态乃幸福本源相关推荐

  1. Java多态与泛型 ,动态绑定,静态绑定

    文章目录 (一)多态 1.概念 1.1 使用继承: 1.2 实现接口(推荐): 2.作用 3.多态的实现原理 3.1 Java 动态绑定以及内部实现机制 程序绑定的概念 关于final.static. ...

  2. 解耦 多态性 java_Java的多态浅谈,Java多态浅谈网站安全分享!

    Java的多态浅谈概述Java的四大基本特性:抽象,封装,继承和多态.其中,抽象,封装,继承可以说多态的基础,而多态是封装,继承的具体表现.如果非要用专业术语来描述什么是多态的话 多态是指程序中定义的 ...

  3. java多态知乎_Java多态的理解

    作者:程序狗 链接:https://www.zhihu.com/questio... 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 不请自来,C++的多态不太清楚. ...

  4. java多态 降低代码耦合性_深度分析:理解Java中的多态机制,一篇直接帮你掌握!...

    Java中的多态 1 多态是什么 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.用白话来说,就是多个对象调用同一 ...

  5. Java多态-如何理解父类引用指向子类对象

    java多态,如何理解父类引用指向子类对象 要理解多态性,首先要知道什么是"向上转型". 我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类.我可以通过   C ...

  6. 笔记1——C++多态与Java多态的异同

    最近参加网易笔试遇到一个问题,考察了C++ 多态特性,自己查了相关资料学习了相关用法. 一般程序调用的函数地址是在编译期决定了,但是具有多态特性的函数调用地址是在程序运行期才决定. C++与Java多 ...

  7. 关于java多态中覆盖的理解

    在前面一篇文章中,我已经介绍了关于java多态中重载的理解与规则 所以这篇文章主要介绍多态中的覆盖机制. 首先重载与覆盖除了表现方式不同之外,还有运行时间上的不同,重载是在编译期间就已经可以确定好调用 ...

  8. 什么是Java多态?如何实现Java多态?

    java多态这个概念在同学们深入学习java的时候就会被提出,很多同学并不知道是什么意思,如何实现.今天小千就来给大家介绍一下什么是java多态和java如何实现多态. 什么是多态? 指允许不同类的对 ...

  9. Java学习笔记二十六:Java多态中的引用类型转换

    Java多态中的引用类型转换 引用类型转换: 1.向上类型转换(隐式/自动类型转换),是小类型到大类型的转换: 2.向下类型转换(强制类型转换),是大类型到小类型的转换: 3.instanceof运算 ...

最新文章

  1. .NET读写Excel工具Spire.Xls使用(1)入门介绍
  2. python使用matplotlib可视化阶梯图、使用step函数可视化阶梯图、可视化时间序列数据的波动周期和规律
  3. mysql主从复制优化_MySql优化之主从复制
  4. day18--django3之Ajax
  5. PMP敏捷图表之价值流程图
  6. java用beaninfo_java 可以使用BeanInfo实现bean实体与map之间的互相转换
  7. eclipse juno_放弃Eclipse Juno
  8. 多个php 链接数据库,ThinkPHP实现多数据库连接的解决方法
  9. Centos出现-bash: unzip: command not found的解决办法
  10. 解放双手---jupyter快捷键
  11. c语言程序设计数字电位器,数字电位器X9C103 100级调节电路和单片机源程序
  12. onnx-tensorrt:builtin_op_importers.cpp:628:5: error: ‘IIdentityLayer’ is not a member of ‘nvinfer1’
  13. 构建之法读书笔记05
  14. 2021-08-08在ubuntu上部署nideshop
  15. 有线网与无线网(WIFI)网速的限制因素与Wifi信道选择
  16. 浏览器沙箱(sandBox)到底是什么?
  17. 吴裕雄--天生自然 诗经:古朗月行
  18. 【考研经验】双非二战山东大学计算机技术初试第二经验贴
  19. 一切归零,一切从这里开始
  20. 计算机打字键盘怎么控制,键盘是怎样分区的,打字时每个手指分别可控制哪些键...

热门文章

  1. 卡片的sak为不支持的类型_Python 植物大战僵尸代码实现(2):植物卡片选择和种植...
  2. 卡片的sak为不支持的类型_泛微OA系统为大型制造业打造内外一体的移动报修平台...
  3. cancel java_Future.cancel()疑难杂症
  4. 无线路由器使用有线的桥接方法。
  5. 4GCPE工业路由器使用方法 4G转WiFi 网口 有线 串口 以太网
  6. SpringBoot时区配置
  7. Victoria(硬盘检测工具)v4.46F绿色版
  8. ffmpeg AVFrame 插入静音帧
  9. 看穿 137 亿光年,中国天眼会帮我们找到「三体星」吗?|创新大会 2021
  10. 为什么我3岁的儿子有不良信用记录?儿童数据泄露问题暗潮汹涌