Java基础语法之多态

news2024/11/26 11:49:02

什么是多态

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

都是吃东西,狗是吃狗粮,猫是吃猫粮

向上转型

本质就是创建一个子类对象,将其当作父类对象来使用

语法格式:父类类型 对象名=new 子类类型();

发生向上转型的场景:

1.直接赋值

2.方法传参

传的是cat,但用Animal类来接收

3.方法返回

方法的重写

什么是方法的重写

重写也称为覆盖,重写只能是子类对父类的方法而言

就是在方法名一样,参数列表一样,方法返回值一样

要求

1.子类重写父类方法是一般方法名一样,参数列表一样,方法返回值一样

2.但方法返回值也可以不同,但必须具有父子关系(协变类型),例如一个返回animal,一个返回dog

3.被重写的方法的访问权限不能比父类的低

4.父类被private,static,final修饰的方法以及构造方法都不可以被重写

5.重写的方法都可以用@override注解来显式指定,这个注解会帮我们进行合法性校验,例如方法名写错了,就会报错

编译器自己提供了重写的方法:在子类中点右键,点生成,里面就有构造函数,getter,setter,重写方法等

注意,所有类的父类默认都是object类

动态绑定

也称为后期绑定,即在编译时无法确定方法的行为,需要等到程序运行时,才能确定具体调用那个类的方法,例如:

在main方法中,将小狗对象赋给了animla类,所以在调用eat时,调用了Dog的eat,这就是动态绑定,绑定到了子类的方法

实际上,在编译阶段,绑定的确实是Animal的eat方法,但是在运行时,最终确定了要绑定的是dog的eat方法,这就是动态绑定,是在后期绑定

静态绑定

也称为前期绑定,早绑定,就是在编译时通过参数就能确定用哪个方法典型代表就是函数的重载。

回看toString

System.out.println(dog);

当dog类没有写toString方法时,编译器就去它的父类里面找,但Animal类也没有,就去Object类里面找

当dog类没有写toString方法而父类里面写了时,编译器就调用父类的

当子类自己写了,就调用自己的

实现多态的条件

1.必须在继承关系下,从而能够发生向上转型

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

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

多态举例

这是将要在main函数中调用的方法

这是父类的eat方法

这是dog类的eat方法

这是cat类的eat方法

这是main函数

那么会输出什么呢?按理说,都调用了eatFunc,而eatFunc里面是有调用了Animal类的eat,按理说是都输出name+正在吃饭,但实际上如下:

这就叫多态,有了重写的方法,有了向上转型(一定得有父子关系),在运行时就会发生动态绑定,绑定到不同的重写方法,使得不同的对象会有不同的行为

注意

在eatFunc中的animal是局部变量,它的类型是Animal类,所以他只能调用Animal类里面的方法,而不能调用它的子类的方法

调用dog类的wangwang就会报错!!!

还是那句话,实际上在编译时调用的的确是Animal类的eat方法,只不过是在运行时绑定到了子类的方法,所以不能直接用父类的引用来调用子类的方法

向下转型

我们知道,上面这段代码是将子类的对象经过向上转型后当成父类使用,这时,这个子类对象就只能调用父类的方法,再无法调用子类特有的方法,那要想调用子类的方法,就要将这个父类引用还原为子类对象即可(再强调一遍,animal的类型是Animal,即animal是一个父类引用;new Dog是产生了一个子类对象,然后将它看作父类来使用),如下:

这就是把animal这个父类引用还原为了子类,(注意这里会有一个类型强转,一定要加上括号,否则会报错),此时就可以调用子类的方法了

错误的的向下转型

把一个cat对象给到了父类,还原时却还原成了dog类,这是错误的向下转型

ClassCastException:类型转换异常

总结

对于向下转型:

本来是猫还原为猫,安全

本来是狗,还原为猫,不安全

总之,向下转型很危险,如何解决:

instanceof

if(animal instanceof Dog) 

这句话的意思是:如果animal是Dog类的一个实例,那么就执行if后面的语句

instanceof是一个二元运算符,目的在于判断它左边的对象是否是它右边的类的实例,如果是就返回true,不是就返回false

例如:

为什么无法运行呢?因为a是一个局部变量,局部变量必须人为初始化

初始化之后为什么还会报错?这是因为左边的对象不可以是那八种基础数据类型

多态的优缺点

1.能够降低圈复杂度,避免重复使用if else

看如下代码,想要按照圆圈,矩形,圆圈,矩形,三角形的顺序画出图形:

class Shape{
    public void draw(){
        System.out.println("画一个图形");
    }
}
class Cycle extends Shape{
    @Override
    public void draw() {
        System.out.println("😊");
    }
}
class Rect extends Shape{
    @Override
    public void draw() {
        System.out.println("长方形");
    }
}
class Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("🔺");
    }
}
public class Test1 {
    public static void main(String[] args) {
        Cycle cycle=new Cycle();
        Rect rect=new Rect();
        Triangle triangle=new Triangle();
        String []str={"cycle","rect","cycle","rect","triangle"};
        for(String x:str){
            if(x.equals("cycle")){
                cycle.draw();
            }
            else if(x.equals("rect")){
                rect.draw();
            }
            else{
                triangle.draw();
            }
        }
    }
}
下面是结果:

这段代码用了好多if语句,太复杂了,用多态来修改一下:

定义一个shape类型的数组,里面的对象的类型是它的子类,这就发生了向上转型,最后再调用重写的方法,实现动态绑定。

2.可扩展能力强

比如还想要画一朵花,只要再写一个花类就可以

3.属性没有多态性

如果父类和子类的成员变量同名了,只可以调用父类的变量

例如父类里面,a=0,子类里面,a=10;下面的语句,打印出来的a是0

要想打印出子类的a,可以进行向下转型,或者直接类型强转

但注意,这就不是多态了

4.构造方法没有多态性

注意:避免在构造方法中调用重写的方法

看下面的代码:

class A{
    public void func(){
        System.out.println("A func()");
    }

    public A() {
        func();
    }
}
class B extends A{
    private int num=1;

    @Override
    public void func() {
        System.out.println("B func()");
        System.out.println(num);
    }
}
public class Test {
    public static void main(String[] args) {
        B b=new B();
    }
}

结果是什么:

当创建一个b时,会先对父类进行构造,也就是进入父类的构造方法,而在父类的构造方法中,调用了func(),由于动态绑定,最终执行到的是子类的func。但由于在执行func()时,父类还没有构造完成,所以更没有轮到子类构造,所以num=1这句话还没来得及执行,所以num暂时是默认初始值0.

所以以后不要在构造函数中调用重写的方法,因为此时子类还没有构造完毕,一旦调用,就会发生动态绑定,可能出现隐藏的极难发现的问题

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

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

相关文章

[Kubernetes]2. k8s集群中部署基于nodejs golang的项目以及Pod、Deployment详解

一. 创建k8s部署的镜像 1.部署nodejs项目 (1).上传nodejs项目到节点node1 (2).压缩nodejs项目 (3).构建nodejsDockerfile 1).创建nodejsDockerfile 具体可参考:[Docker]十.Docker Swarm讲解,在/root下创建nodejsDockerfile,具体代码如下: FROM node #把压缩文件COPY到镜像的…

pycharm多线程报错的问题(未解决)

暂未解决!若有佬知道如何解决,还请不吝赐教~~~先谢过啦 问题描述: 看了一下可能是这里的问题: 根据建议,在walks之前加了 freeze_support() 但是没有效果。 关键是,在jupyter上运行是没有问题的&#x…

逆向获取某音乐软件的加密(js逆向)

本文仅用于技术交流,不得以危害或者是侵犯他人利益为目的使用文中介绍的代码模块,若有侵权请联系作者更改。 老套路,打开开发者工具,直接开始找到需要的数据位置,然后观察参数,请求头,cookie是…

1- Electron 创建项目、初始化项目

Electron官网 Build cross-platform desktop apps with JavaScript, HTML, and CSS | Electron Electron 初始化 初始化项目 - 构造package.json npm init -y 安装Electron模块包 npm i electron -D // 注意!如果报错查看node包是否太高 配置启动脚本 {&quo…

安全护航:迅软DSE加密软件在设计院所图纸文件中的成功案例分享

近年来,随着信息化强国战略和可持续发展方针的推动,国内各大设计院所和建筑机构积极推进信息化建设,将电子文件作为主要的信息存储方式,并将其作为单位内外部信息交换的关键载体。在这一背景下,创新设计作为建筑设计单…

如何实现自己的训练集

在anaconda prompt中查看(conda info -e)、删除(conda remove -n aimbot_env)虚拟环境 其中aimbot_env是虚拟环境的名字 是否要删掉?选y 创建虚拟环境(conda create -n aimbot_env python3.7.4&#xff0…

微信小程序---自定义组件

目录 1.局部引用组件 2.全局引用组件 3.组件和页面的区别 4.自定义组件样式 5.properties属性 6.data和properties的区别 7.数据监听器 8.纯数据字段 9.自定义组件-组件的生命周期 lifetimes节点 10.组件所在的页面的生命周期 pageLifetimes节点 11.插槽 &#x…

Redis设计与实现之简单的动态

目录 一、内部数据结构 二、简单动态字符串 1、sds的用途 实现字符串对象 将sds代替C默认的char*类型 2、Redis中的字符串 sds的实现 3、优化追加操作 4、sds 模块的 API 三、Redis动态字符串的内存分配和释放是如何进行的? 四、Redis动态字符串的扩容策略…

css+js 选项卡动画效果

选项卡上下左右翻转动画效果 <template><div class"web-box"><div class"topTitle"><div class"topTitle1">标题标题</div></div><div class"info-wrap"><div style"width: 100%;h…

互联网加竞赛 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

掌握iText:轻松处理PDF文档-高级篇-添加页眉和页脚

推荐语 本文介绍了如何使用iText编程库为PDF文档添加自定义的页眉和页脚。通过指定位置、大小、字体和颜色等属性&#xff0c;你可以将文本、图像或其他元素添加到每一页的固定位置&#xff0c;实现专业、可读的自定义页眉和页脚效果。这对于需要批量处理大量PDF文档或需要更精…

基于轻量级GhostNet模型开发构建工业生产制造场景下滚珠丝杠传动表面缺陷图像识别系统

轻量级识别模型在我们前面的博文中已经有过很多实践了&#xff0c;感兴趣的话可以自行移步阅读&#xff1a; 《移动端轻量级模型开发谁更胜一筹&#xff0c;efficientnet、mobilenetv2、mobilenetv3、ghostnet、mnasnet、shufflenetv2驾驶危险行为识别模型对比开发测试》 《基…

YOLOv5改进 | 2023卷积篇 | AKConv轻量级架构下的高效检测(既轻量又提点)

一、本文介绍 本文给大家带来的改进内容是AKConv是一种创新的变核卷积&#xff0c;它旨在解决标准卷积操作中的固有缺陷&#xff08;采样形状是固定的&#xff09;&#xff0c;AKConv的核心思想在于它为卷积核提供了任意数量的参数和任意采样形状&#xff0c;能够使用任意数量…

***Cpolar配置外网访问和Dashy

Dashy是一个开源的自托管的导航页配置服务,具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一些网站聚合起来放在一起,形成自己的导航页。一款功能超强大,颜值爆表的可定制专属导航页工具 结合cpolar内网工具,我们实现无需部署到公网服务器…

Spring Boot 3 整合 WebSocket (STOMP协议) 和 Vue 3 实现实时通信

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

基于 Webpack5 Module Federation 的业务解耦实践

前言 本文中会提到很多目前数栈中使用的特定名词&#xff0c;统一做下解释描述 dt-common&#xff1a;每个子产品都会引入的公共包(类似 NPM 包) AppMenus&#xff1a;在子产品中快速进入到其他子产品的导航栏&#xff0c;统一维护在 dt-common 中&#xff0c;子产品从 dt-com…

【Https】工作流程

HTTPS 也是⼀个应用层协议。是在 HTTP 协议的基础上引入了⼀个加密层。 前言 由于Http是明文传输&#xff0c;因此如果有人想修改/截获数据都是非常容易&#xff0c;因此就出现了运营商劫持问题。 加密基础知识 明文密钥>密文 加密 密文密钥>明文 解密 对称加密和非对…

亚马逊云科技 re:Invent 大会 - ElastiCache Serverless模式来袭

亚马逊云科技 re:Invent 大会 - ElastiCache Serverless模式来袭 本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道。 文章目录 亚马逊云…

jenkins 运行接口自动化测试脚本,安装第三方依赖库的一些总结

之前在做接口自动化时&#xff0c;jenkins 执行 job 安装 requirements.txt 中的第三方依赖库时折腾了许久&#xff0c;网上查的解决方案均未生效&#xff0c;后来找出一条解决方法&#xff0c;做个记录&#xff0c;希望帮助到遇到同样问题的小伙伴。 我们都知道可以通过生成 …

软考机考考试第一批经验分享

由于机考的特殊性&#xff0c;考试环境与传统笔试环境有所不同。下面是与考试环境相关的总结&#xff1a; 草稿纸&#xff1a;考场提供足够数量的草稿纸&#xff0c;每位考生都会分发一张白纸作为草稿纸。在草稿纸上需要写上准考证号。如果不够用&#xff0c;可以向监考老师再次…