向上转型 向下转型 重写 多态 ---java

目录

一. 向上转型

1.1 概念

1.2 语法格式 

1.3 动态绑定引入 

1.4 重写的引入 

 1.5向上转型的使用方式

 方式一: 直接赋值

方式二: 通过传参,进行向上转型(多态引入)

方法三:通过返回值, 进行向上转型 

二. 重写

2.1 概念

2.2 重写的格式

2.3 重写的规则

【重写和重载的区别】

 【重写的设计原则】

三. 多态

3.1概念

3.2多态实现条件

3.3 多态的优缺点

 四. 向下转型

4.1 概念

4.2 语法格式

4.3 使用方法


一. 向上转型

1.1 概念

实际就是创建一个子类对象,将其当成父类对象来使用。 父类引用接收子类对象. 

1.2 语法格式 

父类类型 对象名 = new 子类类型 () ;
例:
 Animal animal = new Dog("旺财",10);
//animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。

1.3 动态绑定引入 

 看下述代码:

看到: animal不能访问barks(), 因为在Animal类中没有.

结论:父类引用只能调用父类自己的方法,不能调用子类的.

接下来, dog类中也定义一个eat()方法:

看到:调用了Dog类中的eat()方法

结论:当父类和子类都有eat()方法时,此时通过animal调用eat()方法,调用的是子类中的方法. 

此时发生的动作叫做动态绑定.

动态绑定:编译的时候, 调用父类的eat方法  运行的时候, 绑定到了子类的eat方法中

静态绑定:编译的时候 已经确定调用哪个方法

1.4 重写的引入 

 拿出父类和子类中的eat()进行对比:

发现:

1. 方法名相同

2. 参数列表相同(顺序, 个数, 类型)

3. 返回值相同

 此时发生了重写.(后面讲)二. 重写

 1.5向上转型的使用方式

对上述代码再添加一个Bird类

 方式一: 直接赋值

   子类对象赋值给父类对象

方式二: 通过传参,进行向上转型(多态引入)

   形参为父类型引用,可以接收任意子类的对象

当我们在方法中加入animal.eat(); 如下:

 

看到:

同一个引用 调用了同一个方法

但因为发生了向上转型 引用的对象不一样 所表现的行为不一样

--->我们把这种思想叫做多态.(后面讲)三. 多态

方法三:通过返回值, 进行向上转型 

返回任意子类对象

二. 重写

2.1 概念

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

2.2 重写的格式

1. 方法名相同

2. 参数列表相同(顺序, 个数, 类型)

3. 返回值相同

2.3 重写的规则

1. 当父类中的方法被 final 修饰时, 此方法不能被重写. 这个方法叫做密封方法.

2. 可以在子类方法前加入 @Override 注解来显式指定, 表示此方法是重写方法, 有了这个注解能帮我们进行一些合法性校验.

3. 当父类的方法被 static 修饰时,  此方法不能被重写. 

4.  子类重写方法的访问权限不能比父类中被重写的方法的访问权限更低。

访问修饰限定符:子类 >= 父类

例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected.

5. 当父类中的方法被 private 修饰时, 此方法不能被重写.(private只能在同一类中使用)

6. 父类与子类返回值类型可以不同,但是必须是具有父子关系的  

父类:

子类:

 

 父类与子类返回值类型可以不同,但构成了父子关系, 也是可以的.

*7. 在构造方法中, 避免调用重写的方法. 

例如下述代码:

结果: 

 

看到:

当在父类的构造方法当中,调用父类和子类同名的方法的时候, 此时也会发生动态绑定, 运行时,绑定到了子类的方法中. 

也意味着, 构造方法内, 也会发生动态绑定.

 但为什么num值为0呢?

在之前的学习中, 我们了解到实例化一个对象之后, 简单来说会发生两件事情:

1. 分配内存空间

2. 调用合适的构造方法

所以在new D()之后,为d这个对象分配了一块空间, 也就是为num也分配了空间, 在调用构造方法时, 我们学过顺序:

1. 父类的实例

2. 父类的构造

3. 子类的实例

4. 子类的构造

所以我们首先调用了父类的构造方法, 在方法中调用了子类的func(), 打印了num, 此时num默认值为0, 只有当执行到子类的实例这一步时, num才被初始化为1.

执行顺序如下图:

重写和重载的区别

 

 重写的设计原则

对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容, 并且添加或者改动新的内容。
例如:若干年前的手机,  只能打电话,发短信,来电显示只能显示号码,而今天的手机在来电显示的时候,不仅仅 可以显示号码,还可以显示头像,地区等。在这个过程当中,我们不应该在原来老的类上进行修改,因为原来的 类,可能还在有用户使用 ,正确做法是: 新建一个新手机的类,对来电显示这个方法重写就好了,这样就达到了我 们当今的需求了

三. 多态

3.1概念

通俗来说,就是多种形态, 具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状 态。

3.2多态实现条件

java 中要实现多态,必须要满足如下几个条件,缺一不可:
1. 必须在继承体系下
2. 子类必须要对父类中方法进行重写
3. 通过父类的引用调用重写的方法

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

例:

class Animal{
    String name;
    int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println(this.name +"正在吃...");
    }
}

class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }

    public void eat(){
        System.out.println(this.name +"正在吃狗粮...");
    }

    void bark(){
        System.out.println(name + "汪汪汪~~~");
    }
}

class Bird extends Animal{
    public Bird(String name, int age) {
        super(name, age);
    }

    public void fly(){
        System.out.println(this.name+"正在飞...");
    }
    public void eat(){
        System.out.println(this.name+"正在吃鸟粮...");
    }
}
//分割线
public class test {
            // 注意:此处的形参类型必须是父类类型才可以
    public static void fun(Animal animal){
      animal.eat();
        // 编译器在编译代码时,并不知道要调用Dog 还是 Bird 中eat的方法
        // 等程序运行起来后,形参animal引用的具体对象确定后,才知道调用那个方法
    }
    public static void main(String[] args) {
        Dog dog = new Dog("旺财",10);
        fun(dog);
        Bird bird = new Bird("布谷",1);
        fun(bird);
    }
}

 

在上述代码中 , 分割线上方的代码是 类的实现者 编写的 , 分割线下方的代码是 类的调用者 编写的 .
当类的调用者在编写 eat 这个方法的时候 , 参数类型为 Animal ( 父类 ), 此时在该方法内部并 不知道 , 也不关注 当前的 animal 引用指向的是哪个类型 ( 哪个子类 ) 的实例 . 此时  animal  这个引用调用 eat  方法可能会有多种不同的表现 (  animal  引用的实例相关), 这种行为就称为 多态 .

3.3 多态的优缺点

例下述代码: 

class Shape {
        //属性 ....
        public void draw () {
                System . out . println ( " 画图形! " );
        }
}
class Rect extends Shape {
        @Override
        public void draw () {
                System . out . println ( " " );
        }
}
class Cycle extends Shape {
        @Override
        public void draw () {
                System . out . println ( " " );
        }
}
class Flower extends Shape {
        @Override
        public void draw () {
                System . out . println ( " " );
        }
}

我们现在需要打印多个形状. 如果不基于多态, 实现代码如下:  

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

如果使用使用多态, 则不必写这么多的 if - else 分支语句, 代码更简单.

public static void drawShapes () {
// 我们创建了一个 Shape 对象的数组 .
        Shape [] shapes = { new Cycle (), new Rect (), new Cycle (), new Rect (), new Flower ()};
//向上转型
        for ( Shape shape : shapes ) {
                shape . draw ();
        }
}
使用多态的好处
1. 能够降低代码的 " 圈复杂度 ", 避免使用大量的 if - else
什么叫 " 圈复杂度 " ?
圈复杂度是一种描述一段代码复杂程度的方式 . 一段代码如果平铺直叙 , 那么就比较简单容易理解 . 而如果有很多的条件分支或者循环语句, 就认为理解起来更复杂 .
因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数 , 这个个数就称为 " 圈复杂度 ". 如果一个方法的圈复杂度太高, 就需要考虑重构 .
不同公司对于代码的圈复杂度的规范不一样 . 一般不会超过 10.
2. 可扩展能力更强
如果要新增一种新的形状 , 使用多态的方式代码改动成本也比较低 .
多态缺陷:代码的运行效率降低
1. 属性没有多态性
当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性
2. 构造方法没有多态性

 四. 向下转型

4.1 概念

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

4.2 语法格式

父类类型 对象名 = new 子类类型() ;//向上转型

子类类型 对象名 = (子类类型) 父类对象名 ;//向下转型

4.3 使用方法

1.

结果: 

2. 

 

结果: 

程序可以通过编程,但运行时抛出异常---因为:animal2实际指向的是鸟, 不能强转成狗

所以:

向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。
Java 中为了提高向下转型的安全性,引入了 instanceof ,判断这个对象是否属于这个类型, 如果该表达式为 true ,则可以安全转换。

结果: 

 强转失败

今天的分享就到这里, 谢谢大家的点赞支持! 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring篇】Spring注解式开发

本文根据哔哩哔哩课程内容结合自己自学所得,用于自己复习,如有错误欢迎指正; 我在想用一句话激励我自己努力学习,却想不出来什么惊为天人、精妙绝伦的句子,脑子里全是上课老师想说却没想起的四个字 “ 唯手熟尔 ”&am…

微服务开发中,使用AOP和自定义注解实现对权限的校验

一、背景 微服务开发中,暴露在外网的接口,为了访问的安全,都是需要在http请求中传入登录时颁发的token。这时候,我们需要有专门用来做校验token并解析用户信息的服务。如下图所示,http请求先经过api网关,网…

渗透工具---BurpSuite 插件开发之HelloWorld

本文主要记录如何利用burp官方的新版API即MontoyaApi 写helloworld(上一篇的demo使用旧版api写的,这篇及后续开发将采用新版api) 先看效果图 更多详细内容见下方 这里有更详细更全面的代码内容 以及配置相关的内容 https://mp.weixin.qq.co…

【HarmonyOS】API6上JS实现视频播放全屏播放时,会回到之前界面

【关键字】 API6 / 视频播放 / 全屏播放异常 【问题现象】 开发者在API6上用JS实现视频播放器点全屏播放后,不是全屏效果,实际效果是变成了横屏并返回到首页。 具体代码实现是参考video媒体组件指南。 【问题分析】 JS实现视频播放器有Codelab代码示…

基于springboot实现乒乓球预约管理系统项目【项目源码】计算机毕业设计

基于springboot实现乒乓球预约管理系统演示 系统的开发环境 浏览器:IE 8.1(推荐6.0以上) 开发使用语言:JAVA JDK版本:JDK_8 数据库管理系统软件:Mysql 运行平台:Windows 7 运行环境&#…

HarmonyOS ArkTS语言,运行Hello World(二)

一、认识DevEco Studio界面 进入IDE后,我们首先了解一下基础的界面。整个IDE的界面大致上可以分为四个部分,分别是代码编辑区、通知栏、工程目录区以及预览区。 代码编辑区 1、中间的是代码编辑区,你可以在这里修改你的代码,以…

CRMEB Pro版 v3.0详情预告(附件crmebPro功能思维导图)

首先,先来看看本次CRMEB Pro版 v3.0 的整体升级框架 翩若惊鸿 CRMEB Pro版 从设计之初,就十分重视用户体验,在保证强大功能的同时,本次也为大家带来了领先于业界的UI 3.0,一目惊鸿。 一、风格升级 1、圆角风格 商城…

轻松整理文件夹,将视频文件全部归类到另一个文件夹!

如果你需要整理文件夹中的文件,将同一类别的文件归纳到一起,可以更加方便地管理和查找。现在,我们有一个简单而实用的方法,可以将文件夹中的所有视频文件归类到另一个文件夹中,让你的文件管理更加有序和高效。 首先&am…

动能方案 | 15693协议的读卡器应用 DP1363F 替代RC663

15693协议是一种高频(13.56 MHz)射频识别(RFID)协议,广泛满足无线识别和数据传输领域。其特点包括较远的读取范围、支持快速数据传输、与多个标签的兼容等,产生于不同行业有着广泛的应用,包括但…

10个即时通讯软件开发项目经验教训

即时通讯软件开发在现代社交和商务交流中扮演着重要的角色。然而,这个领域也充满了挑战。在本文中,我将探讨即时通讯软件开发的重要性以及开发者面临的挑战,并分享一些应对策略。 10个经验教训 明确需求:在开始开发之前&#xf…

CRM中线索的概念和使用技巧

CRM中线索是什么?如何管理线索?CRM系统中线索通常指通过展会、线上、广告等方式获取到的原始客户信息。这些潜在的客户信息经过市场培育、SDR筛选,进而成为一个合格商机。下面我们从3个方面介绍什么是线索管理。 1.线索来源 线索来源渠道非…

来吧,SpringBoot的自动配置原理都在这里了

💗推荐阅读文章💗 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》🌺MySQL系列🌺👉2️⃣《MySQL系列教程》🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》…

ELK企业级日志分析平台

目录 一、elasticsearch 1、集群部署 2、cerebro部署 3、elasticsearch-head插件部署 4、elasticsearch集群角色分类 二、logstash 1、部署 2、elasticsearch输出插件 3、file输入插件 4、file输出插件 5、syslog 插件 6、多行过滤插件 7、grok过滤 三、kibana数…

vr小鼠虚拟解剖实验教学平台减少了受感染风险

家畜解剖实验教学是培养畜牧兽医专业学生实际操作能力的专业教学活动中的核心手段。采取新型教学方式与手段,合理设置实验教学内容,有助于激发学生的操作积极性,促进实践教学的改革。 家畜解剖VR仿真教学是一种借助VR虚拟现实制作和web3d开发…

谷歌Freshness新鲜度算法:如何利用它提升网站排名?

今天我们就来深入了解下Google Freshness算法核心,结合案例研究和实用技巧,为我们自己的网站优化提供一些思路。 Google新鲜度算法和QDF Google的新鲜度算法和查询需求的新鲜度(Query Deserves Freshness, QDF)模型是为了改善特…

爱创科技总裁谢朝晖荣获“推动医药健康产业高质量发展人物”

中国医药市场规模已经成为全球第二大医药市场,仅次于美国。近年来,随着中国经济的持续增长和人民生活水平的提高,医药市场需求不断扩大。政府对医疗卫生事业的投入也在不断加大,为医药行业的发展创造了良好的政策环境。为推动医药…

和田2023年群众舞蹈大赛总决赛圆满落幕!

11月19日,由中共和田地委宣传部主办,地区文旅局承办,地区文化馆、各县市文旅局协办,北京市援疆和田指挥部支持的和田地区2023年“大地欢歌 舞动和田”群众舞蹈大赛总决赛在和田市新夜市圆满落幕,比赛最终决出一等奖1名…

laravel引入element-ui后,blade模板中使用elementui时,事件未生效问题(下载element-ui到本地直接引入项目)

背景 重构公司后台项目,使用了dcat-admin,但是dcat-admin有些前端功能不能满足需求。因此引入element-ui进行相关界面的优化 具体流程 1.下载element-ui到本地 2.进入如下目录 打开 node_modules\element-ui\lib 复制index.js 打开 node_modules/ele…

实例讲解Simulink的MATLAB Function模块

内容 MATLAB Function是一个支持使用M语言编写模块功能,并能够将所编写的M语言生成C代码,用于开发桌面应用和嵌入式应用的模块。它支持的 MATLAB内建函数比 Fcn模块要广泛,除去基本的四则运算、逻辑操作符和关系操作符,还可以调用MATLAB各种…

许战海战略文库|从丰田到等离子屏:技术领先为何失去市场?

引言:在探讨技术创新与市场需求之间的微妙关系时,个关键的问题浮现:为什么强大的技术优势并不总是等同于市场成功?从丰田汽车在电动车领域的挑战到日本等离子显示屏技术的衰落,市场趋势对企业成功存在决定性影响。企业需要在技术创新和市场需求之间找到…