【Java0基础学Java第八颗】 -- 继承与多态 -- 多态
8.继承与多态
- 8.2 多态
- 8.2.1 多态的概念
- 8.2.2 多态实现条件
- 8.2.3 重写
- 8.2.4 向上转型和向下转型
- 8.2.5 向下转型
- 8.2.6 多态的优缺点
- 8.2.7 避免在构造方法中调用重写的方法
8.2 多态
8.2.1 多态的概念
通俗来说就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
就比如打印机,彩色打印机和黑白打印机,打印出的效果一个是彩色,一个是黑白。
即:同一件事情,发生在不同对象身上,就会产生不同的结果。
8.2.2 多态实现条件
在Java中要实现多态,必须要满足以下条件:
- 必须在继承体系下
- 子类必须要对父类方法进行重写
- 通过父类的引用调用重写的方法
多态的体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。
8.2.3 重写
重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, **返回值和形参都不能改变。即外壳不变,核心重写!**重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写的规则:
- 方法名一样
- 参数列表相同(个数、数据类型、顺序)
- 返回值一样
注意: 不能被重写的4种情况
- 被final修饰的方法 不可以被重写。这个方法叫做密封方法。
public final void eat() {System.out.println(this.name+" 正在吃。。。");}
- 被static修饰的方法 不能被重写
public static void eat() {System.out.println(this.name+" 正在吃。。。");}
- 子类重写父类方法的时候,子类的方法访问修饰限定符要>=父类

// 父类的方法
//当父类的方法修饰限定符是 默认defau时,子类的方法访问修饰限定符可以是protected、public
public void eat() {System.out.println(this.name+" 正在吃。。。");}//子类的方法
public void eat() {System.out.println(this.name+" 正在吃狗粮...");}
-
- 被private修饰的方法 是不被重写的
重写和重载的区别:
重写的方法名和参数都一样,而重载的方法名相同,参数不同。
即:方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
通过反汇编代码:

动态绑定:子类和父类都有 编译得时候认为 还是确认调用了父类得eat方法
运行得时候 绑定到子类当中
- 父类引用 引用 子类对象;
- 通过父类引用 去调用 父类 和子类 同名的方法。
静态绑定:编译的时候就已经确定调用哪个方法了,如下dog.barks(10);

8.2.4 向上转型和向下转型
向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
语法格式:父类类型 对象名 = new 子类类型()
- 直接赋值
Animal animal = new Dog("旺财",10,"红色"); //直接赋值
- 方法传参
// 方法传参 :形参作为父类引用,可以接受任意子类的对象public static void fun(Animal animal) {animal.eat();// 发生了多态}public static void main(String[] args) {Dog dog = new Dog("旺财",3,"红色");fun(dog);Bird bird = new Bird("布谷",1);fun(bird);}

同一个引用 调用了 同一个方法,当是因为引用的对象不一样,所表现的行为不一样,称为多态。
- 方法返回
// 通过返回值,进行向上转型public static Animal fun2() {return new Dog("旺财",3,"红色");}
向下转型能让代码变得更加简单灵活,缺点就是不能调用到子类特有的方法。
8.2.5 向下转型
Java中为了提高向下转型的安全性,引入了instanceof ,如果该表达式为true,则可以安全转换。
public static void main(String[] args) {Animal animal2 = new Bird("布谷",1);//animal2.eat();//animal2.fly();Bird bird = (Bird) animal2;bird.fly();Animal animal1 = new Dog("旺财",3,"红色");if (animal1 instanceof Bird) {Bird bird2 = (Bird) animal1;bird2.fly();}else {System.out.println("不一定所以的动物都是鸟");}}
8.2.6 多态的优缺点
使用多态的好处:
- 能够降低代码的圈复杂度,避免使用大量的if-else
用if-else:
class Shape {public void draw() {System.out.println("画图形");}
}
class Cycle extends Shape {@Overridepublic void draw() {System.out.println("⚪");}
}
class Rect extends Shape {@Overridepublic void draw() {System.out.println("矩形");}
}class Triangle extends Shape {@Overridepublic void draw() {System.out.println("三角形");}
}
public class Test {public static void main(String[] args) {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();}}}}
用多态:
class Shape {public void draw() {System.out.println("画图形");}
}
class Cycle extends Shape {@Overridepublic void draw() {System.out.println("⚪");}
}
class Rect extends Shape {@Overridepublic void draw() {System.out.println("矩形");}
}class Triangle extends Shape {@Overridepublic void draw() {System.out.println("三角形");}
}
public class Test {// 使用多态public static void main(String[] args) {Rect rect = new Rect();Cycle cycle = new Cycle();Triangle triangle = new Triangle();// 向上转型Shape[] shapes = {cycle,rect,cycle,rect,triangle};for (Shape shape : shapes) {shape.draw();}}
}
- 可扩展能力更强
如果需要新加一种形状,使用多态的方式代码改动成本也比较低
比如新加一个画❀
class Flower extends Shape {@Overridepublic void draw() {System.out.println("❀");}
}
public class Test {public static void main(String[] args) {Rect rect = new Rect(); // 相当于Shape rect = new Rect();Cycle cycle = new Cycle();Triangle triangle = new Triangle();Flower flower = new Flower();// 向上转型Shape[] shapes = {cycle,rect,cycle,rect,triangle,flower};for (Shape shape : shapes) {shape.draw();}}
}
缺点: 代码的运行效率降低
- 属性没有多态性
当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性 - 构造方法没有多态性
8.2.7 避免在构造方法中调用重写的方法
当在父类的构造方法当中,调用父类和子类同名的方法时候,此时也会发生动态绑定。也意味着 构造方法内 也会发生动态绑定。
注意: 在构造方法当中 不要调用重写的方法。
class B {public B() {// 父类的实例 --> 父类的构造 --> 子类的实例 --> 子类的构造func(); // 调用子类的func方法 没有给num赋值 所以num的值为0}public void func() {System.out.println("B.func()");}
}
class D extends B {private int num = 1;public D() {super();}@Overridepublic void func() {System.out.println("D.func() " + num);}
}
public class Test2 {public static void main(String[] args) {//1. 分配内存空间 2. 调用合适的构造方法D d = new D();}
}
- 构造 D 对象的同时, 会调用 B 的构造方法.
- B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func
- 此时 D 对象自身还没有构造, 此时 num 处在未初始化的状态, 值为 0.。
- 所以在构造函数内,尽量避免使用实例方法,除了final和private方法。
结论:用尽量简单的方式使对象进入可工作状态,尽量不要在构造器中调用方法(如果这个方法被子类重写,就会触发动态绑定,但是此时子类对象还没构造完成),可能会出现一些隐藏的但是又极难发现的问题。
相关文章:
【Java0基础学Java第八颗】 -- 继承与多态 -- 多态
8.继承与多态 8.2 多态8.2.1 多态的概念8.2.2 多态实现条件8.2.3 重写8.2.4 向上转型和向下转型8.2.5 向下转型8.2.6 多态的优缺点8.2.7 避免在构造方法中调用重写的方法 8.2 多态 8.2.1 多态的概念 通俗来说就是多种形态,具体点就是去完成某个行为,当…...
玩转ansible之参数调试和文件操作篇
更多IT技术文章,欢迎关注微信公众号“运维之美” 玩转ansible之参数调试和文件操作篇 01 剧本调试和帮助02 使用场景举例 上节我们学习了使用ansible进行软件安装,那么安装完软件后,就需要linux系统和软件配置修改了,对于linux主机…...
JVM虚拟机:垃圾回收器之Parallel Old(老年代)
本文重点 本文将学习老年代的另外一种垃圾回收器Parallel Old(PO),这是一种用于老年代的并行化垃圾回收器,它使用标记整理算法进行垃圾回收。 历史 在1.6之前,新生代使用Parallel Scavenge只能搭配老年代的Serial Old收集器,而…...
Stream流的groupingBy
Stream流的groupingBy 简单使用 业务场景:现在有100个人,这些人都年龄分部在18-30岁之间。现要求把他们按照年龄进行分组 key:年龄 value:数据列表 public void listToMapGroup() {//这里假设通过listStreamService.list();方法…...
如何在不结束tcpdump的情况下复制完整的pcap
tcpdump正在运行的时候,他写入的pcap可能是不完整的,通常我们要结束掉tcpdump才能拿到完整的pcap,否则wireshark打开的时候会提示:The capture file appears to have been cut short in the middle of a packet。这可能是因为tcpd…...
maven POM文件总体配置说明
<project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd "> <!-- 父项目的坐…...
49.批处理命令(1/2)
目录 一批处理。 (1)批处理定义。 (2)常见命令。 (2.1)rem和:: (2.2)echo和。 (2.3)pause。 (2.4)errorlevel。 (…...
react类式组件的生命周期和useEffect实现函数组件生命周期
概念 生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是vue还是react都具有这个设计概念,也是开发者必须熟练运用的,特别是业务开发,不同的生命周期做不同的事是很重要的. ....多说两句心得,本人是先接触vue的,无论是vue2还是vue3的生命周期,在理解和学习上都会比react更…...
ARM 基础学习记录 / 异常与GIC介绍
GIC概念 念课本(以下内容都是针对"通用中断控制器(GIC)"而言,直接摘录的,有的地方可能不符人类的理解方式): 通用中断控制器(GIC)架构提供了严格的规范&…...
java压缩pdf体积,图片体积
pdf整体进行压缩,图片进行压缩 // 生成主证书的PDF路径 创建一个文件String pdfPath UploadDown.createFile(".pdf");outputStream new FileOutputStream(pdfPath);bufferedOutputStream new BufferedOutputStream(outputStream);writer PdfWriter.getInstance(…...
Ubuntu(WSL2) 安装最新版本的 GCC
要在 Ubuntu 上安装最新版本的 GCC,可以通过以下步骤进行操作: 1. 打开终端(Terminal) 2. 更新软件包列表,确保系统使用最新的软件包信息,运行以下命令: sudo apt update 3. 安装 GCC 软件包…...
lua 时间差功能概略
简介 在进行程序设计过程中,经常需要对某些函数、某些程序片断从开始运行到运行结束所耗费的时间进行一些量化。这种量化实际上就是计算时间差。 获取函数耗时情景如下: function time_used() --开始计时-- do something at here. --结束计时--时间差&…...
【C++11】左值引用,右值引用,移动/复制构造,完美转发
左值与右值 字面意思是可以放在等号左边的就是左值,只能放在等号右边的就是右值(为何是“可以”“只能”?例如i是左值,但他依然可以放在等号右边)。 严格上的定义:可以取地址的就是左值,反之为…...
解决找不到x3daudio1_7.dll的方法,快速解决x3daudio1_7.dll丢失问题
在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是“找不到x3daudio1_7.dll”。这个问题可能是由于多种原因引起的,例如文件丢失、损坏或被病毒感染等。下面将详细介绍如何解决这个问题。 首先,我们需要了解x3daudio1_…...
LeetCode:2300. 咒语和药水的成功对数(C++)
目录 2300. 咒语和药水的成功对数 题目描述: 实现代码与解析: 二分 原理思路: 2300. 咒语和药水的成功对数 题目描述: 给你两个正整数数组 spells 和 potions ,长度分别为 n 和 m ,其中 spells[i] 表…...
【Spring生命周期核心底层源码之剖析】
文章目录 一、Spring生命周期核心底层源码剖析—扫描1.1、Spring底层扫描机制doScan方法源码剖析 一、Spring生命周期核心底层源码剖析—扫描 1.1、Spring底层扫描机制doScan方法源码剖析 其源代码如下: protected Set<BeanDefinitionHolder> doScan(Strin…...
关于Thread.sleep方法的一些使用
Thread.sleep方法的作用就是使当前线程暂停执行一段指定的时间。 它的参数是以ms为单位的时间参数,表示暂停时间长度。如Thread.sleep(1000);表示暂停1s。 这个方法通常用在以下一些情况: 1、模拟延迟:在某些情况下,我们希望在…...
MeterSphere | 前端入参加密
项目场景: 在 MeterSphere 开源框架中,解决前端手机号入参加密 解决方案: 导入 JavaScript 包采用加密算法 导入网上 JavaScript 包 // 1. 通过cdn加载网上的js文件 g new Packages.org.mozilla.javascript.tools.shell.Global(Packages.o…...
微服务如何做负载均衡?
笔者在参与联通某子公司时,遇到了这样一个问题。感觉比较实际,特来记录一波。 先看腾讯混元的解答: 微服务架构中,负载均衡是必不可少的。在微服务中,负载均衡可以通过以下几种方式来实现: 1. DNS轮询&am…...
C++高级编程:构建高效稳定接口与深入对象设计技巧
C高级编程:构建高效稳定接口与深入对象设计技巧 建立稳定接口 类是C中的主要抽象单位。你应该将抽象原则应用于你的类,尽可能将接口与实现分离。具体来说,你应该使所有数据成员私有,并可选择性地提供getter和setter方法。这就是…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》
近日,嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》,海云安高敏捷信创白盒(SCAP)成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天,网络安全已成为企业生存与发展的核心基石,为了解…...
在Zenodo下载文件 用到googlecolab googledrive
方法:Figshare/Zenodo上的数据/文件下载不下来?尝试利用Google Colab :https://zhuanlan.zhihu.com/p/1898503078782674027 参考: 通过Colab&谷歌云下载Figshare数据,超级实用!!࿰…...
python打卡第47天
昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图,展示模…...
