什么是java的多态

什么是java的多态多态分为两种a.编译时多态:方法的重载;b. 运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态。(我们平时说得多的事运行时多态,所以多态主要也是指运行时多态);上述描述认为重载也是多态的一种表现,不过多态主要指运行时多态。2.运行时多态a.面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。…

大家好,又见面了,我是你们的朋友全栈君。

多态分为两种

a. 编译时多态:方法的重载;

b. 运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态。(我们平时说得多的事运行时多态,所以多态主要也是指运行时多态);

上述描述认为重载也是多态的一种表现,不过多态主要指运行时多态。

2.运行时多态

a. 面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。

b. 多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

c. 实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

d. 多态的作用:消除类型之间的耦合关系。

e. 现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。

下面是多态存在的三个必要条件,要求大家做梦时都能背出来!

多态存在的三个必要条件
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。

 多态的好处

1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

3.代码理解

看了上面的描述,我们大概知道以下几点:

a. 运行时多态是在父类引用指向子类对象时产生的。一个父类的引用可以指向多种子类对象,那么运行时对于同一个消息应该如何做出响应呢?这就由实际的被引用的对象的类型来决定。

b. 为什么要有重写呢?难道父类中的方法没有被重写,直接调用子类中存在的方法难道是不行吗?看个例子如下:

什么是java的多态

上面的例子中,当父类中的getName()被注释掉以后,调用father.getName()方法会出错。因此,当父类引用指向子类方法时,必须调用那些父类中存在的方法,如果子类中对该方法进行了重写,那么在运行时就会动态调用子类中的方法,这就是多态。

c. 要有继承很好理解,没有继承的话,哪来的重写呢。

4.深一点

基本了解了多态以后,我们就可以看明白下面这个例子了,它的输出结果是什么呢?

什么是java的多态

答案是”son”,结合前面的解释,我们很容易判断出来。子类的getName()方法重写了父类中的方法,在main中,父类的引用father指向了子类的对象son,当我们调用father的getName()方法时,实际上是动态绑定到了子类的getName()上,所以会打印出”son”。

5.再深一点

你是否真正理解了多态呢?请看下面的例子:

什么是java的多态

上面这个例子中,下面四条语句的输出结果是什么呢?

a1.show(b);
a1.show(c);
a2.show(b);
a2.show(c);

结果如下:

 什么是java的多态

对于前两条语句的结果我们很容易理解,那第三条和第四条的,为什么结果和我们想的不一样,不应该是”B and B”吗?要理解这是为什么,我们要先理解下面这句话:

当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。 (但是如果强制把超类转换成子类的话,就可以调用子类中新添加而超类没有的方法了)

看一下标红的那句话,我们知道问题所在了吗?

当运行 a2.show(b) 的时候,实际是要调用一个 show(B obj) 的方法,但是 A 中有这样一个方法吗?没有!但是由于 B 继承自 A,所以会调用 A 中的 show(A obj) 的方法,但是调用时候发现这个方法已经被 B 重写了,所以就会转向来调用 B 中的 show(A obj) 方法。所以才会打印出”B and A”。

实际上这里涉及方法调用的优先问题 ,优先级由高到低依次为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。让我们来看看它是怎么工作的。

比如,a2.show(b),a2是一个引用变量,类型为A,则this为a2,b是B的一个实例,于是它到类A里面找show(B obj)方法,没有找到,于是到A的super(超类)找,而A没有超类,因此转到第三优先级this.show((super)O),this仍然是a2,这里O为B,(super)O即(super)B即A,因此它到类A里面找show(A obj)的方法,类A有这个方法,但是由于a2引用的是类B的一个对象,B覆盖了A的show(A obj)方法,因此最终锁定到类B的show(A obj),输出为”B and A”。

怎么样?理解了吗?

 

问题还要继续,现在我们再来看上面的分析过程是怎么体现出红色字体那句话的内涵的。它说:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。还是拿a2.show(b)来说吧。

 

a2是一个引用变量,类型为A,它引用的是B的一个对象,因此这句话的意思是由B来决定调用的是哪个方法。因此应该调用B的show(B obj)从而输出”B and B”才对。但是为什么跟前面的分析得到的结果不相符呢?!问题在于我们不要忽略了蓝色字体的后半部分,那里特别指明:这个被调用的方法必须是在超类中定义过的,也就是被子类覆盖的方法。B里面的show(B obj)在超类A中有定义吗?没有!那就更谈不上被覆盖了。实际上这句话隐藏了一条信息:它仍然是按照方法调用的优先级来确定的。它在类A中找到了show(A obj),如果子类B没有覆盖show(A obj)方法,那么它就调用A的show(A obj)(由于B继承A,虽然没有覆盖这个方法,但从超类A那里继承了这个方法,从某种意义上说,还是由B确定调用的方法,只是方法是在A中实现而已);现在子类B覆盖了show(A obj),因此它最终锁定到B的show(A obj)。这就是那句话的意义所在,到这里,我们可以清晰的理解Java的多态性了。

 

6. 最后一个练习!

看下面的例子:

什么是java的多态

上面例子中的输出是什么呢?答案是:ai ni

有了前一个例子我们就会很容易理解这个例子。在B类中是没有对A中的show方法进行重写,所以当a.show()时调用的是父类中的show方法,父类中show方法调用了show2方法,但是在调用的时候发现show2方法已经被子类重写,因此会调用子类中show2方法,因此输出”ai”。可见,当父类引用指向子类对象的时候,对父类中方法的调用都会绑定到子类中重写后的方法上,如果子类没有对方法进行重写,那么会直接调用父类中的方法,相当于是直接调用从父类继承的方法

还需要注意的一点是子类在重写父类的方法时,方法的访问权限不能更低!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/156582.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月7日 下午9:46
下一篇 2022年7月7日 下午9:46


相关推荐

  • 2021最新java详细学习路线及路线图(超详细)「建议收藏」

    2021最新java详细学习路线及路线图(超详细)「建议收藏」本文将告诉你学习Java的一些步骤,学习过程中可能遇到的问题,及学习路线。希望能够对你的学习有所帮助。文末给大家准备了惊喜,希望大家都能够坚持看完哦~一、Java基础二、Java学习七大阶段[阶段1、JavaSE基础][阶段2、WEB前端][阶段3、数据库][阶段4、JavaWeb][阶段5、JavaWeb项目][阶段…

    2022年6月16日
    24
  • idea 2022 Mac 激活码【中文破解版】

    (idea 2022 Mac 激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html4KDDGND3CI-eyJsaWN…

    2022年4月1日
    468
  • QThread介绍

    QThread介绍在程序设计中,为了不影响主程序的执行,常常把耗时操作放到一个单独的线程中执行。Qt对多线程操作有着完整的支持,Qt中通过继承QThread并重写run()方法的方式实现多线程代码的编写。针对线程之间的同步与互斥问题,Qt还提供了QMutex、QReadWriteLock、QwaitCondition、QSemaphore等多个类来实现。本篇博客将针对以下几个方面进行讲解[1]QThread的常用接口以及QThread的实现[2]QThread的信号事件[3]QThread执行完后自动释放内存

    2022年5月28日
    121
  • linux vim 编辑 保存 退出

    linux vim 编辑 保存 退出一 进入文件 vim etc profile 二 编辑文件按 i 进行编辑三 保存与退出 1 首先按 esc 键返回命令编辑模式 刚才的 Insert 会消失 2 按英文状态的 3 此时进行 q 不保存文件 强制退出 vi 命令 w 保存文件 不退出 vi 命令 wq 保存文件 退出 vi 命令 4 输入以上命令按 enter 进行

    2026年3月17日
    2
  • CFileDialog的使用方法简单介绍

    CFileDialog的使用方法简单介绍

    2021年11月30日
    52
  • HTTP 302错误和HTTP 404错误浅析

    HTTP 302错误和HTTP 404错误浅析HTTP302 错误和 HTTP404 错误浅析 HTTP 返回状态码的含义比较丰富 随着 HTTP 版本的变化 状态码也在逐渐增加 以满足越来越多的状态信息传递 nbsp nbsp nbsp nbsp nbsp 302 错误表示被请求的资源暂时转移 Movedtempora 然后会给出一个转移后的 URL 而浏览器在处理服务器返回的 302 错误时 原则上会重新建立一个 TCP 连接 然后再取重定向后的 URL 的页面 但是如果页面存在于缓存中

    2026年3月17日
    19

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号