【Java SE】多态
🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈
文章目录
- 1. 多态
- 1.1 多态是什么
- 1.2 多态的意义
- 1.3 多态的实现条件
- 2. 重写
- 2.1 重写的概念
- 2.2 重写的规则
- 2.3 重写与重载的区别
- 2.4 重写的设计
- 3. 向上转型和向下转型
- 3.1 向上转型
- 3.2 向下转型
- 3.3 instanceof关键字
- 4. 多态的优缺点
- 4.1 多态的优点
- 4.2 多态的缺点
1. 多态
面向对象三大特性:封装、继承、多态
今天我们一起来看看多态这一特性~~~
1.1 多态是什么
在生活中,如果遇到特别伤心的事情或者心情很沮丧,可能就会哭泣,但在不同人身上,哭泣的形式不一样,比如"臣妾做不到",小女孩哇哇大哭,还有大耳朵图图抱着妈妈的腿哭泣等等。总之,同一件事情,发生在不同对象上,表现的形式是不一样的~
【多态】通俗来说,多种形态,即去完成某个行为,当不同的对象去完成时会产生出不同的状态
1.2 多态的意义
【多态的意义】
在于提高代码的复用性和扩展性,同时实现接口统一,并十分灵活,可以根据不同的输入参数或条件,调用不同的子类方法实现不同的功能,易于维护和修改(本期内容结尾将重点提到)
1.3 多态的实现条件
在Java中实现多态的条件如下(缺一不可):
(1) 必须在继承下
(2) 子类必须要对父类中方法进行重写
(3) 通过父类的引用调用重写的方法(向上转型)
多态体现的方面:当传递不同类对象时,会调用对应类中的方法
【代码】
public class Animal {String name;String gender;int age;public Animal(String name,String gender, int age) {this.name = name;this.gender = gender;this.age = age;}public void eat() {System.out.println(name+"吃饭");}
}
public class Cat extends Animal{public Cat(String name,String gender,int age) {super(name, gender, age);}@Overridepublic void eat() {System.out.println(name+"吃🐟");}
}
public class Dog extends Animal{public Dog(String name,String gender,int age) {super(name, gender, age);}@Overridepublic void eat() {System.out.println(name+"吃骨头");}
}
public class Bird extends Animal{public Bird(String name,String gender,int age) {super(name, gender, age);}@Overridepublic void eat() {System.out.println(name+"啄米");}
}
public class Test {public static void eat(Animal a) {a.eat();}public static void main(String[] args) {Cat cat = new Cat("柚子","雌",2);Dog dog = new Dog("球球","雄",1);Bird bird = new Bird("泡芙","雌",2);eat(cat);eat(dog);eat(bird);}
}
【运行结果】
【解释说明】
在上述代码中,Animal、Cat、Dog和Bird类是类的实现者写的,Test类是类的调用者写的
当类的调用者在编写 eat 这个方法的时,传进来的参数类型为 Animal父类,在该方法内部并不知道当前的a 引用指向的是哪个类型,哪个子类的实例,即a这个引用调用 eat方法可能会有多种不同的表现(a引用的实例相关,比如猫类实例调用、狗类实例调用等,eat表现的形式不同),这种行为称为多态
【图示】
【@Override】
@Override是jdk的注解,用于指示一个方法是重写了父类中的方法
这个注解只在编译时有效,不会保留在生成的字节码文件中
使用 @Override 注解的优点:
1)提高代码的可读性和安全性
2)在编译时检查可能的错误
但它不是必需要写的,只要正确地重写了父类中的方法,不使用 @Override 注解,代码仍能够正常运行
(即使用或不使用取决于编码风格和习惯)
2. 重写
2.1 重写的概念
【重写】也称为覆盖,重写是子类对父类实现过程进行重新编写, 返回值和形参都不能改变,即外壳不变,核心重写,重写的好处是子类可以根据需要,定义特定于自己的行为,即子类能够根据需要实现父类的方法
2.2 重写的规则
【重写规则】
1)子类在重写父类的方法时,一般必须与父类的返回值类型 ,方法名 (参数列表) 完全一致
2)被重写的方法返回值类型可以不同,但必须具有父子类关系
3)访问权限不能比父类中被重写的方法的访问权限更低(如父类方法被public修饰,则子类中重写该方法不能声明为 private)
4)父类被static、private、final修饰的方法、构造方法都不能被重写
5)重写的方法可使用 @Override 注解来显式指定,能进行一些合法性校验,检查可能会出现的错误(如不小心将方法名字写错, 此时编译器就会发现父类中没有该方法,则编译报错,提示无法构成重写)
2.3 重写与重载的区别
2.4 重写的设计
【重写的设计原则】对于已经投入使用的类,尽量不要进行修改,最好是重新定义一个新的类,重复利用其中共性的内容,并添加或者改动新的内容
举一个栗子吧~
例如之前的电视机,只能看正在播放的频道,而当今时代,科技越来越发达,技术在进步,现在的电视不仅可以看正在播放的频道,还可以回看,直播等等,而我们不应该直接在原来的类修改,因为原来的类可能仍有用户正在使用,而正确的解决方式为,新建一个新型电视机的类,对可以看的内容这个方法进行重写,增添更多的功能,即达到需求
【静态绑定】即在编译时,根据用户所传递实参类型就确定具体调用哪个方法,代表:函数重载
【动态绑定】即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用哪个类的方法(发生多态的基础)
3. 向上转型和向下转型
3.1 向上转型
【向上转型】实际上是创建一个子类对象,当父类对象使用
【语法格式】父类类型 对象名 = new 子类类型();
【语法举例】
Animal animal = new Bird(“泡芙”,“雌”,2);
animal是父类Animal类型,即小的范围变成大的范围(是可以的),比如猫、狗和鸟等都是动物,将子类对象转化为父类引用是合理、安全的,大的范围包含小的范围
【使用场景】
1)直接赋值 2)方法传参 3)方法返回 【具体使用代码举例如下】:
public class Test1 {public static void main(String[] args) {Cat cat = new Cat("柚子","雌",2);Dog dog = new Dog("球球","雄",1);//1.直接复制 子类对象赋值给父类对象Animal bird = new Bird("泡芙","雌",2);eat(cat);eat(dog);eat(bird);}//2.方法传参 形参的类型为Animal父类,可接受任意子类对象,即animal1的类型可以是猫、狗、鸟等子类public static void eat(Animal animal1) {animal1.eat();}//3.方法返回 返回任意子类对象public static Animal guessAnimal(String name) {if("球球".equals(name)) {return new Dog("球球","雄",1);}return null;}
}
【优点】
让代码实现更简单灵活
【缺点】
不能调用到子类特有的方法,只能调用父类的方法
3.2 向下转型
【向下转型】子类对象向上转型后当父类对象方法使用,再无法调用子类的方法,如需调用子类特有的方法,将父类引用再还原为子类对象即可,即向下转型,在Java中,向下转型是从一个更通用的类型向一个更具体的类型转换的过程
【语法格式】子类对象名 = (子类类型) 对象名
【语法举例】
bird = (Bird)animal;
【使用场景】
将它们转回具体的类型以利用它们的具体实现的情况
public class Animal {String name;String gender;int age;public Animal(String name,String gender, int age) {this.name = name;this.gender = gender;this.age = age;}public void eat() {System.out.println(name+"吃饭");}
}
public class Cat extends Animal{public Cat(String name,String gender,int age) {super(name, gender, age);}@Overridepublic void eat() {System.out.println(name+"吃🐟");}public void meow() {System.out.println("猫在叫~");}
}
public class Dog extends Animal{public Dog(String name,String gender,int age) {super(name, gender, age);}@Overridepublic void eat() {System.out.println(name+"吃骨头");}public void bark() {System.out.println("狗在叫~");}
}
public class Bird extends Animal{public Bird(String name,String gender,int age) {super(name, gender, age);}@Overridepublic void eat() {System.out.println(name+"啄米");}public void chirp() {System.out.println("小鸟叫~");}}
public class Test2 {public static void main(String[] args) {Cat cat = new Cat("柚子","雌",2);Dog dog = new Dog("球球","雄",1);Bird bird = new Bird("泡芙","雌",2);//向上转型Animal animal = cat;animal.eat();animal = dog;animal.eat();animal = bird;animal.eat();//向下转型//程序可以通过编程但是会抛出异常,animal实际指向的是鸟,但现在强制还原为猫,无法还原//cat = (Cat)animal;//cat.meow();//animal指向的是鸟,将animal还原为鸟是安全的bird = (Bird)animal;bird.chirp();//instanceof 判断它左边的对象是否是它右边的类的实例,返回boolean的数据类型,是返回true否则返回false;if(animal instanceof Cat) {cat = (Cat)animal;cat.meow();}if(animal instanceof Dog) {dog = (Dog)animal;dog.bark();}//animal指向的是鸟,左边的对象animal是右边鸟类的实例,为true,执行if内容语句if(animal instanceof Bird) {bird = (Bird) animal;bird.chirp();}}
}
【运行结果】
【解释说明】
【优点】
可访问更具体类型的特定方法和属性,明确正在处理的具体类型
【缺点】
不安全,万一转换失败,运行时会抛异常,Java中为了提高向下转型的安全性,引入instanceof关键字 ,如该表达式为true,则可以安全转换,较为麻烦
3.3 instanceof关键字
【概念】instanceof是Java中的保留关键字
【作用】测试它的左边对象是否是它的右边类的实例,返回类型:boolean类型
【用法】res = 对象名 instanceof 类名;
【举例】以上述代码举例
4. 多态的优缺点
4.1 多态的优点
1)能够避免使用大量的 if - else
如果需要打印多个形状,不基于多态写,则会有好几个if语句
public class Shape {public void draw() {System.out.println("画图形~");}
}
public class Rectangle extends Shape{@Overridepublic void draw() {System.out.println("◇");}
}
public class Cycle extends Shape{@Overridepublic void draw() {System.out.println("○");}
}
public class Fish extends Shape{@Overridepublic void draw() {System.out.println("🐟");}
}
public class Test3 {public static void drawShapes() {Rectangle rectangle = new Rectangle();Cycle cycle = new Cycle();Fish fish = new Fish();String[] shapes = {"cycle","rectangle","fish"};for(String x : shapes) {if(x.equals("cycle")) {cycle.draw();}else if(x.equals("rectangle")) {rectangle.draw();}else if(x.equals("fish")) {fish.draw();}}}public static void main(String[] args) {drawShapes();}
}
基于多态编写代码,创建一个Shape对象的数组,则简洁明了~
public class Test3 {public static void drawShapes1() {Shape[] shapes = {new Cycle(),new Rectangle(),new Fish()};for(Shape x: shapes) {x.draw();}}public static void main(String[] args) {drawShapes1();}
}
两者打印结果一致,所以可以避免大量的if-else语句
2)可扩展能力更强
如果要新增加一种新的形状,使用多态方式编写的代码改动成本较低,体现可扩展性强,比如我们要增加三角形这个形状类型
public class Triangle extends Shape{@Overridepublic void draw() {System.out.println("△");}
}
【解释说明】基于多态代码,对类的使用者来说,drawShapes方法只需创建一个新类的实例,改动成本较低,对于不基于多态的代码, 则需把drawShapes方法中的 if - else 进行修改,改动成本更高
4.2 多态的缺点
代码的运行效率降低
1)属性没有多态性,当父类和子类都有同名属性时,通过父类引用只能引用父类自己的成员属性
2)构造方法没有多态性
A为父类,在A类构造方法中调用func()方法,B为子类,B类中重写func()方法
【代码举例】
public class A {public A() {func();}public void func() {System.out.println("A.func()");}
}
public class B extends A{private String str = "~";@Overridepublic void func() {System.out.println("B.func()"+" "+str);}
}
public class Test4 {public static void main(String[] args) {B b = new B();}
}
【运行结果】
【解释说明】
构造B对象的同时,会调用A的构造方法
A的构造方法中调用func()方法,此时会触发动态绑定,即在编译时不能确定方法的行为,等程序运行时,确定是具体调用B类中的 func()方法,此时B对象自身还没有构造, str是未初始化的状态,为null,如果具备多态性,str的值应该是~,即构造方法没有多态性
【结论】在构造函数内,尽量避免使用实例方法,除final和private方法
即尽量不要在构造器中调用方法,如果这个方法被子类重写,就会触发动态绑定,但此时子类对象还没构造完成,可能会出现一些隐藏但很难发现的问题,带来不必要的麻烦
💛💛💛本期内容回顾💛💛💛
✨✨✨本期内容到此结束啦~下期再见!
相关文章:
【Java SE】多态
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. 多态1.1 多态是什么1.2 多态的意义1.3 多态的实现条件 2. 重写2.1 重写的概念2.2 重写的规则2.3 重写与重…...
Yarn vs npm的大同小异Yarn是什么?
Yarn vs npm的大同小异&Yarn是什么? 一、Yarn、npm是什么?二、Yarn vs npm:特性差异总结 一、Yarn、npm是什么? npm是Node.js的包管理器,是由Chris Korda维护。 npm,它全称为Node Package Manager,是…...
1.Godot引擎|场景|节点|GDS|介绍
Godot介绍 Godot是一款游戏引擎 可以通过在steam商城免费下载 初学者和编程基础稍差的推荐学习使用GDScript,和python有些相似 Godot节点 Godot的开发思想——围绕节点 节点的特征与优势 最常用基本的开发组件大部分都具有具体的功能,如图片…...
springboot3 redis 实现分布式锁
分布式锁介绍 分布式锁是一种在分布式系统中用于控制不同节点上的进程或线程对共享资源进行互斥访问的技术机制。 在分布式环境中,多个服务可能同时访问和操作共享资源,如数据库、文件系统等。为了保持数据的一致性和完整性,需要确保在同一…...
2024年第十四届MathorCup数学应用挑战赛A题思路分享(妈妈杯)
A题 移动通信网络中PCI规划问题 物理小区识别码(PCI)规划是移动通信网络中下行链路层上,对各覆盖小区编号进行合理配置,以避免PCI冲突、PCI混淆以及PCI模3干扰等现象。PCI规划对于减少物理层的小区间互相干扰(ICI),增加物理下行控制信道(PDCCH)的吞吐量有着重要的作用,尤其…...
运动听歌哪款耳机靠谱?精选五款热门开放式耳机
随着人们对运动健康的重视,越来越多的运动爱好者开始关注如何在运动中享受音乐。开放式蓝牙耳机凭借其独特的设计,成为了户外运动的理想选择。它不仅让你在运动时能够清晰听到周围环境的声音,保持警觉,还能让你在需要时与他人轻松…...
Kubernetes学习笔记12
k8s核心概念:控制器: 我们删除Pod是可以直接删除的,如果生产环境中的误操作,Pod同样也会被轻易地被删除掉。 所以,在K8s中引入另外一个概念:Controller(控制器)的概念,…...
Qt Designer 控件箱中的控件介绍及布局比列分配
控件箱介绍 Qt Designer的控件箱(Widget Box)包含了各种常用的控件,用户可以通过拖放的方式将这些控件添加到窗体设计器中,用于构建用户界面。以下是一些常见控件箱中的控件及其功能的讲解: 1.基本控件&#…...
蓝桥集训之三国游戏
蓝桥集训之三国游戏 核心思想:贪心 将每个事件的贡献值求出 降序排序从大到小求和为正是即可 #include <iostream>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int N 100010;int a[N],b[N],c[N];…...
MySQL知识整理
MySQL知识整理 基础第一讲:基础架构:一条SQL查询语句是如何执行的?架构尽量减少长连接的原因和方案为什么尽量不要依赖查询缓存 索引第四讲:深入浅出索引(上)第五讲:深入浅出索引(下…...
代码随想录算法训练营第36天| 435. 无重叠区间、 763.划分字母区间*、56. 合并区间
435. 无重叠区间 力扣题目链接 代码 示例代码 class Solution { public:// 按照区间右边界排序static bool cmp (const vector<int>& a, const vector<int>& b) {return a[1] < b[1];}int eraseOverlapIntervals(vector<vector<int>>&a…...
SpringBoot整合Nacos
文章目录 nacosnacos下载nacos启动nacos相关配置demo-dev.yamldemo-test.yamluser.yaml 代码pom.xmlUserConfigBeanAutoRefreshConfigExampleValueAnnotationExampleDemoApplicationbootstrap.yml测试结果补充.刷新静态配置 nacos nacos下载 下载地址 一键傻瓜试安装即可,官…...
vue3 浅学
一、toRefs 问题: reactive 对象取出的所有属性值都是⾮响应式的 解决: 利⽤ toRefs 可以将⼀个响应式 reactive 对象的所有原始属性转换为 响应式的 ref 属性 二、hook函数 将可复⽤的功能代码进⾏封装,类似与vue2混⼊。 三、ref:获取元素或者组件 let …...
三小时使用鸿蒙OS模仿羊了个羊,附源码
学习鸿蒙arkTS语言,决定直接通过实践的方式上手,而不是一点点进行观看视频再来实现。 结合羊了个羊的开发思路,准备好相应的卡片素材后进行开发。遇到了需要arkTS进行解决的问题,再去查看相应的文档。 首先需要准备卡片对应的图片…...
如何使用 ArcGIS Pro 制作热力图
热力图是一种用颜色表示数据密度的地图,通常用来显示空间分布数据的热度或密度,我们可以通过 ArcGIS Pro 来制作热力图,这里为大家介绍一下制作的方法,希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的POI数…...
SpringBoot之集成Redis
SpringBoot之集成Redis 一、Redis集成简介二、集成步骤2.1 添加依赖2.2 添加配置2.3 项目中使用 三、工具类封装四、序列化 (正常都需要自定义序列化)五、分布式锁(一)RedisTemplate 去实现场景一:单体应用场景二&…...
mybatis-plus与mybatis同时使用别名问题
在整合mybatis和mybatis-plus的时候发现一个小坑,单独使用mybatis,配置别名如下: #配置映射文件中指定的实体类的别名 mybatis.type-aliases-packagecom.jk.entity XML映射文件如下: <update id"update" paramete…...
MySQL基础知识——MySQL日志
一条查询语句的执行过程一般是经过连接器、 分析器、 优化器、 执行器等功能模块, 最后到达存储引擎。 那么, 一条更新语句的执行流程又是怎样的呢? 下面我们从一个表的一条更新语句进行具体介绍: 假设这个表有一个主键ID和一个…...
uniapp 地图分幅网格生成 小程序基于map组件
// 获取小数部分 const fractional function(x) {x Math.abs(x);return x - Math.floor(x); } const formatInt function(x, len) {let result x;len len - result.length;while (len > 0) {result 0 result;len--;}return result; }/*** 创建标准分幅网格* param …...
python项目练习——22、人脸识别软件
功能分析: 人脸检测: 识别图像或视频中的人脸,并标记出人脸的位置和边界框。 人脸识别: 识别人脸的身份或特征,通常使用已知的人脸数据库进行训练,然后在新的图像或视频中识别出人脸并匹配到相应的身份。 表情识别: 识别人脸的表情,如高兴、悲伤、愤怒等,并给出相应…...
Linux中账号登陆报错access denied
“Access denied” 是一个权限拒绝的错误提示,意味着用户无法获得所请求资源的访问权限。出现 “Access denied” 错误的原因可以有多种可能性,包括以下几种常见原因: 错误的用户名或密码:输入的用户名或密码不正确,导…...
python语言之round(num, n)小数四舍五入
文章目录 python round(num, n)小数四舍五入python round(num, n)基础银行家舍入(Bankers Rounding)利息被银行四舍五入后,你到底是赚了还是亏了? python小数位的使用decimal模块四舍五入(解决round 遇5不进) python round(num, n…...
安全风险攻击面管理如何提升企业网络弹性?
从研究人员近些年的调查结果来看,威胁攻击者目前非常善于识别和利用最具有成本效益的网络入侵方法,这就凸显出了企业实施资产识别并了解其资产与整个资产相关的安全态势的迫切需要。 目前来看,为了在如此复杂的网络环境中受到最小程度上的网络…...
常用的几款性能测试软件
Apache JMeter是一款免费、开源的性能测试工具,广泛应用于Web应用程序和服务的性能测试。它支持模拟多种不同类型的负载,可以测试应用程序在不同压力下的性能表现,并提供丰富的图表和报告来分析测试结果。 优点: 免费且开源&…...
谷歌google浏览器无法更新Chrome至最新版本怎么办?浏览器Chrome无法更新至最新版本
打开谷歌google浏览器提示:无法更新Chrome,Chrome无法更新至最新版本,因此您未能获得最新的功能和安全修复程序。点击「重新安装Chrome」后无法访问此网站,造成谷歌浏览器每天提示却无法更新Chrome至最新版本。 谷歌google浏览器无…...
认识异常(1)
❤️❤️前言~🥳🎉🎉🎉 hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥&a…...
C++矩阵
C矩阵【基本】(will循环) #include<iostream> #include<string.h> using namespace std; int main() {int a[100][100]{0};int k 1;int i 0;int j 0;while(k<100){if(j>10){j0;i;}a[i][j]k;j;k;}i 0;j 0;while(true){if(i 9&am…...
解锁智能未来:用Ollama开启你的本地AI之旅
Ollama是一个用于在本地运行大型语言模型(LLM)的开源框架。它旨在简化在Docker容器中部署LLM的过程,使得管理和运行这些模型变得更加容易。Ollama提供了类似OpenAI的API接口和聊天界面,可以非常方便地部署最新版本的GPT模型并通过…...
CSS实现卡片在鼠标悬停时突出效果
在CSS中,实现卡片在鼠标悬停时突出,通常使用:hover伪类选择器。 :hover伪类选择器用于指定当鼠标指针悬停在某个元素上时,该元素的状态变化。通过:hover选择器,你可以定义鼠标悬停在元素上时元素的样式,比如改变颜色、…...
GPT建模与预测实战
代码链接见文末 效果图: 1.数据样本生成方法 训练配置参数: --epochs 40 --batch_size 8 --device 0 --train_path data/train.pkl 其中train.pkl是处理后的文件 因此,我们首先需要执行preprocess.py进行预处理操作,配置参数…...
外国小孩和大人做网站/正规代运营公司排名
本书的作用 本书会帮助你跨过“原理听起来不错,但还是有点儿新,不太适应”的门槛,从而熟练地编程。 “也许吧,”你可能会想,“可是Lambda、函数式编程,这些不是那些留着胡子、穿着凉鞋的学究们在象牙塔里面…...
怎么做网站的在线客服/百度seo优化网站
使用dbua升级时,需要手工设置CLUSTER_DATABASE参数么? 来源于: Is Manual Setting Of CLUSTER_DATABASE Parameter Required For DBUA Upgrade? (文档 ID 741081.1) 适用于: Oracle Server - Enterprise Edition - Version: 10.…...
做天然文化石的网站/chrome浏览器官网入口
很多用户在购买完3TB(4T,6T,8T等硬盘同样适用本方法,以下简称3T)以上硬盘回家后,装上机器时会显示硬盘容量被“偷走”746GB,这究竟是什么原因呢?在这里我们先了解一下,为什么硬盘在Win7系统中也会有容量限制࿱…...
怎样做相亲网站/西安网站建设公司十强
传统的MVP: 1、抽离出View的接口,即ILoginView。 2、抽离Model的接口,即ILoginModel。 3、抽离Presenter的接口,即ILoginPresenter。 4、实现ILoginView 接口的 LoginActivity。 5、实现ILoginModel 接口的 LoginModel。 6、实现I…...
做二手房的端口网站/下载百度网盘app
前言 在项目中频繁遇到数组、集合和泛型,在使用vue时,用到最多的是数组;在后台时使用最多的是泛型,有时还用到IList,下面来学习一下它们之间的关系。 正文 数组 概念 一组类型相同的有序数据,它是…...
wordpress直接密码注册/视频营销成功的案例
问题发生: Java从网络批量读取图片并保存至本网站服务器后再插入文章中 今天转入一篇文章 http://news.qq.com/a/20170605/045860.htm 发现图片未能成功上传 查看源码发现: 因为没有文件类型所以在转存图片的时候出错了 谷歌百度了一下发现解决办法&…...