【Java基础篇 | 面向对象】—— 聊聊什么是多态(下篇)

个人主页:兜里有颗棉花糖
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
收录于专栏【JavaSE_primary】
本专栏旨在分享学习JavaSE的一点学习心得,欢迎大家在评论区讨论💌
在这里插入图片描述

目录

  • 一、动态绑定和静态绑定
    • 动态绑定
    • 静态绑定
  • 二、向上转型和向下转型
    • 向上转型
    • 向下转型
  • 三、多态的优缺点
  • 四、避免在构造方法中去调用重写的方法

一、动态绑定和静态绑定

动态绑定

动态绑定(也叫晚绑定或者运行时绑定):在编译时不能确定方法的行为,需要等到程序运行时才能够确定调用的具体是哪个类中的方法。

什么时候会用到动态绑定:
当一个子类继承自一个父类并重写了父类的方法时,就会涉及到Java的动态绑定。在运行时,实际上调用的是子类重写后的方法,而不是父类的方法。
举个栗子:在这里插入图片描述
解释:子类Dog重写了父类Animal中的eat方法,在main方法中创建了一个Animal类型的引用animal,并将其实例化为Dog对象。最后通过调用它的eat方法,会根据实际对象的类型,动态地绑定到对应的方法上。
代码编译时的确调用的是父类Animal中的eat方法,但是最终运行结果是调用了子类中的eat方法(本质就是因为这里发生了重写,同时这里是通过父类来去调用子类中重写的这个eat方法的)。

动态绑定发生之前必须具备两个条件:

  • 第一:父类和子类中必须存在重写的方法。
  • 第二:通过父类的引用来去调用重写的方法。

静态绑定

静态绑定(也称为早绑定):在编译时,根据用户所传递参数个数、实参类型等就可以确定具体调用哪个方法。

比如我们之前学过的重载就是很好的一个静态绑定的例子。
举个栗子:

public add(int a,int b,int c) {return a + b + c;
}public void eat(int a,int b) {return a + b;
}

二、向上转型和向下转型

向上转型

向上转型:简单来说就是用父类引用来接受子类对象

向上转型发生的三种时机:直接赋值传参返回值

第一种时机:
直接赋值的方式:Animal animal = new Dog("cc",10);

第二种时机:传参。
在这里插入图片描述

第三种时机:返回值。
在这里插入图片描述

再来回顾多条的概念:父类引用引用子类对象时,当引用的子类对象的对象类型不一样时,通过父类引用去调用父类和子类重写的方法,此时同一个引用可以呈现出不同的状态,我们把这个思想称之为多态。官方一点:多态是指对象根据其实际的类型来执行不同的操作或表现出不同的行为的能力。

向上转型优点:让代码实现更加灵活。
向上转型缺点:不能调用子类特有的方法而只能调用父类和子类重写的方法。

向下转型

重要的事情放前面:向下转型不是很安全,一般很少用到。

向下转型概念:将一个子类对象经过向上转型之后当成父类方法使用,此时就无法调用子类的特有方法(而只能调用父类和子类重写的方法);但是有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。

向下转型是非常不安全的,转换失败的话运行时就会抛出异常。所以Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。
举个栗子:
在这里插入图片描述
下面这种方式才是安全的使用方法:
在这里插入图片描述

三、多态的优缺点

多态优点:能够降低代码的 “圈复杂度”, 避免使用大量的 if - else
多态缺点:可扩展能力更强

降低代码的 “圈复杂度”,举栗请看如下代码:

class Shape {public void draw() {System.out.println("什么图形?");}
}
class Rect extends Shape{@Overridepublic void draw() {System.out.println("矩形");}
}
class Cycle extends Shape{@Overridepublic void draw() {System.out.println("圆形");}
}class Triangle extends Shape {@Overridepublic void draw() {System.out.println("三角形");}
}

现在我们如果想打印不同的图形,如果基于多态来实现的话,代码如下:

public static void drawShapes() {Rect rect = new Rect();Cycle cycle = new Cycle();Triangle triangle = new Triangle();String[] shapes = {"cycle", "rect", "cycle", "rect", "triangle"};for (String shape : shapes) {if (shape.equals("cycle")) {cycle.draw();} else if (shape.equals("rect")) {rect.draw();} else if (shape.equals("triangle")) {triangle.draw();}}}

如果我们基于多态来进行实现的话,代码只有那么几行,请看:

public static void drawShapes2() {// 这里创建了一个 Shape 对象的数组.Shape[] shapes = {new Cycle(), new Rect(), new Cycle(),new Rect(), new Triangle()};for (Shape shape : shapes) {shape.draw();}}

至于多态的拓展能力强这里优点,我们还是拿上面的代码进行举栗:除了上述图形之外,我们还可以添加其它各种各样的图形。

多态缺陷:
1.属性是没有多态性的:方法我们可以进行重写,但是属性是不可进行重写的(当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性)。
2.我们应该避免在构造方法中去调用重写的方法(具体为啥请看下面一小节)。

四、避免在构造方法中去调用重写的方法

我们还是拿代码进行举例,请看:

class B {public B() {func();}public void func() {System.out.println("B.func()");}
}
class D extends B {private int num = 1;@Overridepublic void func() {System.out.println("D.func() " + num);}
}
public class Test {public static void main(String[] args) {D d = new D();}
}

运行结果如下:
在这里插入图片描述

上述代码有以下几个点需要我们注意:

  • 构造 D 对象的同时, 会调用 B 的构造方法。
  • B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func。(由于此时 D 对象自身还没有构造, 所以num 处在未初始化的状态。
  • 所以在构造函数内,尽量避免使用实例方法,除了final和private方法。

在构造方法中调用重写方法可能会导致意想不到的结果。因为在对象初始化时,子类重写的方法可能还没有被执行,所以调用该方法可能会得到父类中的默认实现,而不是子类所期望的行为。

好了,以上就是本文的全部内容啦,就到这里吧。再见啦友友们!!!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/193555.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

opencv几何变换和图像形态学

实验1 实验内容 该代码演示了如何使用OpenCV库中的WarpAffine函数进行图像基础的仿射变换 代码注释 import numpy as np import cv2 as cvimg cv.imread(rtest.jpg, 1) rows, cols, channels img.shape M np.float32([[1,0,100],[0,1,50]]) res cv.warpAffine(img, M, …

【微信小程序】上传头像 微信小程序内接小程序客服

这里写目录标题 微信小程序上传头像使用button按钮包裹img 微信小程序内接小程序客服使用button按钮跳转客服 微信小程序上传头像 使用button按钮包裹img 原本思路是只使用image标签再加上chooseImg,但发现使用button标签上传头像这种方法更实用。微信小程序文档上…

C++实现DFS、BFS、Kruskal算法和Prim算法、拓扑排序、Dijkstra算法

背景: 实现要求: 根据图的抽象数据类型的定义,请采用邻接矩阵来存储图1,采用邻接表来存储图2,并完成如下操作:对图1无向图进行深度优先遍历和广度优先遍历。对图1无向图采用Kruskal算法和Prim算法得出最小…

如何保持高能量

精力管理 精力管理对于平衡多项任务和保持热情至关重要。 通过自我积极反馈循环系统培养积极的内心声音。 培养仪式和习惯来控制内心的声音并保持能量。 学习语言带来正能量和宝贵的技能 保持高能量需要自我赋权和体力充电。 经常锻炼有很多好处,包括改善健康…

BLIP和BLIP2

1.BLIP BLIP的第一个共享是将图像文本理解与图像文本生成任务进行了统一,形成了多模态统一模型,模型在ITC任务上的效果也比CLIP更好。 1.1任务 ITC:就是CLIP中的图像文本对比学习任务 ITM:针对ITC任务中匹配不正确的样本&#…

FreeRtos第一个task是怎么run起来的

第一个task是怎么起来的呢?分析完vTaskStartScheduler,就会有答案了。 那vTaskStartScheduler()干了啥呢? 一、创建prvIdleTask task 二、xTimerCreateTimerTask里创建prvTimerTask task 三、初始化一些全局变量 3.1 xNextTaskUnblockTime…

业务数据治理体系化实施流程学习总结

目录 一、业务数据治理实施流程 步骤 1:发现问题和制定目标 步骤 2:针对问题进行拆解,设计可衡量的指标 步骤 3:制定解决SOP和检查研发标准规范 步骤 4:推广运营,以拿结果为核心目标 步骤 5&#xff…

navicat某些表为什么不按主键排序

不知道大家注没注意过navicat的这种情况 为什么不是按主键排序呢 我们来全表扫描看下他的执行计划 explain select * from orsql3; 可以发现不是全表扫描而是索引树扫描,由此得知了共性,不按主键顺序排序的表,肯定是在二级索引上就保存着全部…

计算机网络体系的形成

目录 1、开放系统互连参考模型OSI/RM 2、两种国际标准 3、协议与划分层次 4、网络协议的三要素 5、划分层次 (1)文件发送模块使两个主机交换文件 (2)通信服务模块 (3)接入网络模块 6、分层带来的好…

pytorch 模型量化quantization

pytorch 模型量化quantization 1.workflow1.1 PTQ1.2 QAT 2. demo2.1 构建resnet101_quantization模型2.2 PTQ2.3 QAT 参考文献 pytorch框架提供了三种量化方法,包括: Dynamic QuantizationPost-Training Static Quantization(PTQ&#xff0…

随心玩玩(十)git

写在前面:研究生一年多了,一直浑浑噩噩的,在深度学习的泥潭挣扎了好久,终于走出了精神内耗的泥潭…好久没有写博客了,决定重新捡起来…记录一下学习吧~ 之前写了一篇git的博客,【github 从0开始的基本操作…

Ubuntu 22.04安装mysql-server 8.0.34(使用bundle.tar)

《Ubuntu 20.04 使用mysql-server_8.0.31-1ubuntu20.04_amd64.deb-bundle.tar安装MySQL 8.0.31》是我以前写的博客。 https://downloads.mysql.com/archives/community/是社区版的官网,可以选择版本下载。 sudo wget -c https://downloads.mysql.com/archives/ge…

【数据库原理】函数依赖、三范式、视图、事务、数据库设计(概念、逻辑、物理结构设计,实施)、数据流图、数据字典、存储过程、触发器、备份与还原【我统统拿下!】

函数依赖 函数依赖是关系数据库中的重要概念,用于描述关系中属性之间的依赖关系。 在关系数据库中,如果关系 R 中的某个属性或属性组的值能够唯一确定关系中其他属性的值,那么我们就说这个属性或属性组对其他属性具有函数依赖关系。 举个例…

分享84个节日PPT,总有一款适合您

分享84个节日PPT,总有一款适合您 84个节日PPT下载链接:https://pan.baidu.com/s/1TSIGR8ZIytnTKmQRa0rGnw?pwd6666 提取码:6666 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整理更不易…

ADC欠采样以及应用案例

欠采样与其优劣 ADC(Analog-to-Digital Converter)的欠采样是指在信号的采样过程中,采样频率低于被采样信号的最高频率的情况。这意味着采样率不足以捕捉到信号的完整信息,而是以较低的频率对信号进行采样。 欠采样在某些特定情…

使用Java语言实现变量互换

一、 java运算 通过异或运算符实现两个变量的互换 import java.util.Scanner;public class ExchangeValueDemo {public static void main(String[] args){try (Scanner scan new Scanner(System.in)) {System.out.println("请输入A的值:");long A sca…

分割YooChoose数据集为YooChoose1/4、YooChoose1/64

目的 源YooChoose数据集十分庞大,有上千万级别的数据,在测试验证模型性能时加载起来十分费劲。 脚本思路 使用数据集中session_id作为滤网对源数据进行过滤,过滤出2百万个不同的session_id作为训练集。 具体步骤 (1)…

TA-Lib学习研究笔记(二)——Overlap Studies上

TA-Lib学习研究笔记(二)——Overlap Studies 1. Overlap Studies 指标 [BBANDS, DEMA, EMA, HT_TRENDLINE, KAMA, MA, MAMA, MAVP, MIDPOINT, MIDPRICE, SAR, SAREXT, SMA, T3, TEMA, TRIMA, WMA]2.数据准备 get_data函数参数(代码&#x…

javaee实验:文件上传及截器的使用

目录 文件上传ModelAttribute注解实验目的实验内容实验过程项目结构编写代码结果展示 文件上传 Spring MVC 提供 MultipartFile 接口作为参数来处理文件上传。 MultipartFile 提供以下方法来获取上传的文件信息:  getOriginalFilename 获取上传的文件名字&#x…

HttpRunner自动化测试之响应中文乱码处理

响应中文乱码: 当调用接口,响应正文返回的中文是乱码时,一般是响应正文的编码格式不为 utf-8 导致,此时需要根据实际的编码格式处理 示例: 图1中 extract 提取title标题,output 输出 title 变量值&#x…