【剧前爆米花--爪哇岛寻宝】面向对象的三大特性——封装、继承以及多态的详细剖析(中——多态)。

news2025/1/11 14:16:34

作者:困了电视剧

专栏:《JavaSE语法与底层详解》

文章分布:这是一篇关于Java面向对象三大特性——多态的文章,在本篇文章中我会分享多态的一些基础语法以及类在继承时代码的底层逻辑和执行顺序。

目录

多态的定义及实现条件

多态的概念

多态的实现条件

方法重写

重写的规则和与重载的对比

静态绑定

动态绑定

向上转型和向下转型

向上转型

向下转型

多态的优点和注意事项


多态的定义及实现条件

class Animal{
    String name;
    int age;
    String sex;
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
    
}

class Cat extends Animal{
    public void eat(){
        System.out.println("吃狗粮");
    }
}

class Dog extends Animal{
    public void eat(){
        System.out.println("吃猫粮");
    }
}

以这段代码作为栗子。 

多态的概念

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态。总的来说:同一件事情,发生在不同对象身上,就会产生不同的结果。

多态在上述栗子的体现中就是Animal都有吃饭这一行为,但在猫和狗中就体现了不同的状态,即狗吃狗粮,猫吃猫粮。

多态的实现条件

1. 必须在继承体系下

2. 子类必须要对父类中方法进行重写

3. 通过父类的引用调用重写的方法

多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。

在上述栗子中,我的Cat类和Dog类都继承了Animal 类,同时在子类中我又对父类中的eat方法进行了重写,最后我只需要在main函数中用父类的引用调用子类重写的方法即可,这样一个Animal就可以根据我的需要既表现出Cat的eat行为,又表现出Dog的eat行为,从而实现了多态。

方法重写

重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程 进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定 于自己的行为。 也就是说子类能够根据需要实现父类的方法。

重写的规则和与重载的对比

1.子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致

2.被重写的方法返回值类型可以不同,但是必须是具有父子关系的 

3.访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方 法就不能声明为 protected

4.父类被static、private修饰的方法、构造方法都不能被重写。

5.重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心 将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法 构成重写.

静态绑定

静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代 表函数重载。

动态绑定

动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体 调用那个类的方法。

public class Javabit_Code {

    public static void main(String[] args) {
        Animal an1=new Cat();
        an1.eat();
        System.out.println("==============");
        Animal an2=new Dog();
        an2.eat();
    }
}

class Animal{
    String name;
    int age;
    String sex;
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }

}

class Cat extends Animal{
    public void eat(){
        System.out.println("吃猫粮");
    }
}

class Dog extends Animal{
    public void eat(){
        System.out.println("吃狗粮");
    }
}

以这段代码为例,当程序在进行编译的时候,程序无法确定我们回去调用哪一个eat,只有当程序运行起来的时候程序才会知道,此时程序底层就发生了动态绑定,这里的动态其实也就是运行的意思。我们可以看一下程序的底层逻辑。

我们可以清楚地看到程序在进行编译的时候,由于不知道会调用哪一个子类的重写方法,于是直接调用父类的方法,当程序运行的时候,这个方法再通过动态绑定从而执行指定的子类的方法。

 

对于动态绑定的过程可以简单举例理解为,父类的方法的地址为0x88,编译时将父类方法和地址存储在一个地方A,父类方法地址对应的就是0x88,当运行的时候,程序知道了我此时要调用的是Cat的eat方法,于是就将Cat重写的eat方法的地址拿出来并将 A这个地方中父类方法对应的地址改为Cat方法的地址,然后得以运行。

向上转型和向下转型

向上转型

向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。

比如:

Animal animal=new Cat();

animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。

向上转型的优点:让代码实现更简单灵活,当我们在做一些项目的时候,在方法传参等方面会有巨大的便利。

向上转型的缺陷:不能调用到子类特有的方法。 

这个不能调用不是代表子类对象中没有,而是由于存储在栈区中的是父类的引用类型,这个引用类型只能指向自己类中拥有的成员,对子类中独有的成员无法进行指向。

向下转型

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的 方法,此时:将父类引用再还原为子类对象即可,即向下转换。

对于向下转型,由于是大的转小的,所以会非常的不安全,举个栗子:

如果animal对象此时不是向下转型的父类就会报错,为了避免这一问题,Java的研发团队引入了instanceof关键字,他可以帮我们判断类和对象之间的关系,帮助我们减少错误。 

多态的优点和注意事项

1. 能够降低代码的 "圈复杂度", 避免使用大量的 if - else

什么叫 "圈复杂度" ? 圈复杂度是一种描述一段代码复杂程度的方式. 一段代码如果平铺直叙, 那么就比较简单容易理解. 而如 果有很多的条件分支或者循环语句, 就认为理解起来更复杂. 因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数, 这个个数就称为 "圈复杂度". 如果一个方法的圈复杂度太高, 就需要考虑重构. 不同公司对于代码的圈复杂度的规范不一样. 一般不会超过 10 .

2. 可扩展能力更强 如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低.

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

 比如这段代码,他的执行结果为D.func() 0。

这段代码可以作为之前知识的检测,他的执行顺序为:实例父类的成员变量——》执行父类的构造方法——》父类的构造方法中有func方法,于是调用func方法——》子类D中重写了func方法所以此时发生动态绑定即调用子类的func方法——》父类B成员尚未完成实例化,所以此时的D类中成员并没有实例化——》此时的num取默认值即0——》输出D.func() 0。

结论: "用尽量简单的方式使对象进入可工作状态", 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触 发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题.

以上就是本篇博客的全部内容,如有疏漏还请指正!如有帮助,还请三连! 

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

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

相关文章

AWS动手实验 - 创建一个Web3网站

实验操作和录播 亚马逊云科技开发者社区 注意事项 按照操作手册进行即可,需要注意到的几个地方: 1:EC2 的 scale 可以不用设置为large那么高,small就够用了。 2:创建堆栈,是点击这个那个按钮&#xff0…

水土保持监测,无人机倾斜摄影该如何做?

水土监测在传统监测方法中存在着许多监测死角。近年来,随着无人机的普及,无人机倾斜摄影三维建模技术在水土保持领域发挥了巨大作用。 我国具有地形地貌范围广,地质情况复杂等特点,每年地质灾害造成很多人员伤亡和财产损失&#…

数商云SCM管理系统库存管理功能助力新能源汽车企业仓储管理更高效

在全球电动化浪潮下,新能源汽车近年来迎来快速发展,但同时,随之而来其面临的关键零部件供应链安全问题也愈来愈突出,新能源汽车供应链格局正在面临重塑,保障新能源汽车产业健康发展仍需持续发力。 随着国际形势突变&a…

Markdown基本语法

描述 Markdown 是一种轻量级的「标记语言」,可读、直观、学习成本低。 1. 强调 1.1 斜体(单*、单_) 例: *AlexYY* _AlexYY_ 效果: AlexYY AlexYY 1.2 加粗(双*、双_) 例: *Ale…

python常用代码总结2

1、列表的常规追加元素、追加列表操作 (1)列表追加多个元素,比如追加0-9 ls [] ls.extend(list(range(10)))ls Out[20]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (2)列表追加多个相同的元素,比如追加10个0 ls1 [] for i in range(10):ls1.append(0)ls1 Ou…

如何通过链路追踪进行定时任务诊断

作者:千习 背景简介 什么是定时任务 定时任务是业务应用系统中存在定时周期性运行的业务逻辑。由于其运行于后端进程中往往存在执行状态和执行链路的不可见性《常见定时任务技术方案》。 https://developer.aliyun.com/article/882393 什么是链路追踪 随着分布式…

[附源码]计算机毕业设计springboot基于微信小程序的网络办公系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

zookeeper集群环境搭建及使用

文章目录前提条件下载解压配置文件集群配置测试常用命令前提条件 操作系统:CentOS7服务器:3台Java环境:JDK1.8。安装教程参考JDK1.8安装 下载 执行cd /usr/local进入安装的目录执行命令wget https://archive.apache.org/dist/zookeeper/zo…

ThreadPoolExecutor类是如何保证线程池正确运行的

ThreadPoolExecutor类中的重要属性 在ThreadPoolExecutor类中,存在几个非常重要的属性和方法,接下来,我们就介绍下这些重要的属性和方法。 ctl相关的属性 AtomicInteger类型的常量ctl是贯穿线程池整个生命周期的重要属性,它是一…

LRU Cache【理论讲解 + 代码实现】

LRU Cache📖1. 什么是LRU Cache📖2. 为什么需要LRU算法?📖3. LRU Cache的实现📖1. 什么是LRU Cache LRU是Least Recently Used的缩写,意思是最近最少使用. 它是一种Cache替换算法. 什么是Cache? 狭义的…

校园论坛(Java)—— 登录注册和用户信息模块

校园论坛(Java)—— 登录注册和用户信息模块 文章目录校园论坛(Java)—— 登录注册和用户信息模块1、写在前面2、系统结构设计2.1 各个页面之间的调用关系2.2. 登录注册模块各层的设计3、登录注册模块设计3.1 用户注册功能3.2 用户…

HighTec 工程配置详解

HighTec 工程配置详解 编译配置 构建配置管理器 管理器内,可以创建各种不同用途的配置项。例如用于生产工程的 ROM 配置,用于调试工程的 Debug 配置。对于每个配置,所设置的工程属性是单独分开的,互相之间没有影响。 打开构建配…

[附源码]计算机毕业设计springboot咖啡销售平台

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Unity复刻骑砍中的帝国象棋(一)

Unity复刻骑砍中的帝国象棋(一) 起因和简介 这两天从一款游戏中发现了这么个棋类小游戏,觉得挺有意思,没错,就是下面这个: 作为程序员的我,一下就想到复刻它一下。这个棋类小游戏&#xff0c…

【程序人生】4年创作纪念日,不忘初心,继续前行

📫作者简介:小明java问道之路,专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…

JavaScript --04. 流程控制语句介绍

文章目录流程控制1 代码块1.1 声明代码块1.2 let 和 var的作用域2 条件判断语句 -- if语句3 条件分支语句3.1 if-else语句3.2 if-else if-else语句3.3 练习4 Switch语句5 循环语句5.1 While循环5.2 do-while循环5.3 for循环5.4 嵌套循环6 break和continue6.1 break6.2 continue…

PTL智能拣货系统

一、PTL背景介绍 随着工业 4.0 理念持续扩展并被接受,智能制造将是中国制造业发展趋势。未来的生产企业不仅仅在生产过程中追求智能化,仓储、工具、设备智能化管理都会成为新的趋势。 现阶段物流仓储行业进入了一个快速的发展期,各种各样的…

辣椒疫霉RXLR效应子抑制植物免疫

文章信息 题目:A Phytophthora capsici RXLR effector targets and inhibits the central immune kinases to suppress plant immunity 刊名:New Phytologist 作者:Xiangxiu Liang,Daolong Dou et al. 单位:China …

微信无感知检测单项好友【WeTool 免费版】【微信如何检测单向好友?】

一.微信无感知检测单项好友 1.1 背景 因为最近业务的原因加了好多的陌生微信好友,难免有很多好友删了我,但是我还有他的微信,岂不是很占地方? 所以我琢磨如何检测这些单项好友【利用转账、拉群的方法太费时间】,我无…

[附源码]计算机毕业设计springboot拉勾教育课程管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…