【Java基础篇 | 面向对象】--- 聊聊什么是多态(上篇)
个人主页:兜里有颗棉花糖
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
收录于专栏【JavaSE_primary】
本专栏旨在分享学习JavaSE的一点学习心得,欢迎大家在评论区讨论💌
目录
- 一、什么是多态
- 二、多态的实现条件
- 三、重写
- 重载和重写的方法
- 四、向上转型和向下转型
- 4.1向上转型
- 4.2向下转型
一、什么是多态
多态的概念:简单来说,多态就是指同一个方法名在不同的对象上有不同的行为。
多态实现的核心概念是方法的重写和动态绑定。当子类继承父类并重写了父类的方法时,可以通过父类引用指向子类对象,并调用该方法,此时会根据对象的实际类型来决定调用哪个类的方法,从而实现多态性。
二、多态的实现条件
在java中,要实现多态的话有3个条件且这三个条件缺一不可:
1.必须是在继承体系下
2.子类必须要对父类中的方法进行重写
3.通过父类的引用调用重写的方法
那多态具体是如何体现的呢:
当传递不同类对象时,会调用对应类中的方法。
三、重写
重写概念:允许子类重新定义父类中已经存在的方法,并提供自己特定的实现。
方法重写的规则如下:
- 子类在重写父类方法时,返回值类型、方法名、参数列表要完全相同。
- 被重写的方法返回值类型可以不同,但是必须是具有父子类关系的。
- 重写是子类对父类非private修饰、非final修饰、非构造方法等的实现过程进行重新编写。(所以如果父类的方法被private、final、static修饰的话,子类就无法对父类的方法重写。被final修饰的方法称为密封方法,不能被重写)
- 访问权限不能比父类中被重写的方法的访问权限更低。
- 构造方法不能被重写(构造方法只能被重载)。
- 当子类重写父类的方法时,可以使用@Override注解来提醒编译器进行检查,确保方法名和参数正确地覆盖了父类的方法。
下面是方法重写的代码演示,请看:
class Person{public String name;public int age;Person(String name,int age){this.name = name;this.age = age;System.out.println("Person(String name,int age)");}public void fun(){System.out.println(name+",你今天开不开心");}
}
class Student extends Person {public int mark;public Student(String name,int age,int mark){super(name,age);this.mark = mark;System.out.println("Student(String name,int age,int mark)");}@Overridepublic void fun(){System.out.println(name+"今天的作业太多了,不是很开心");}
}
class Teacher extends Person{public int wages;public Teacher(String name,int age,int wages){super(name,age);this.wages = wages;System.out.println("Teacher(String name,int age,int wages");}
}
public class Test {public static void main(String[] args) {Student s1 = new Student("Daming",18,100);s1.fun();}
}
运行结果如下:
重载和重写的方法
重载 | 重写 | |
---|---|---|
方法名称 | 必须相同 | 必须相同 |
返回值类型 | 返回值类型不做要求 | 返回值可以相同,但是不同时必须构成父子类关系 |
参数列表 | 参数列表不同(个数、数据类型、顺序) | 参数列表相同 |
范围 | 重载的方法要在同一个类中 | 被重写的类和要重写的类必须构成继承关系 |
四、向上转型和向下转型
4.1向上转型
向上转型:创建一个子类对象,将其当成父类对象来进行使用。
语法格式:父类类型 对象名 = new 子类类型();
向上转型的使用场景有三种:直接赋值、方法传参、方法返回。
这里直接以代码进行举例了:
class Person{public String name;public int age;Person(String name,int age){this.name = name;this.age = age;System.out.println("Person(String name,int age)");}public void fun(){System.out.println(name+",你今天开不开心");}
}
class Student extends Person {public int mark;public Student(String name,int age,int mark){super(name,age);this.mark = mark;System.out.println("Student(String name,int age,int mark)");}@Overridepublic void fun(){System.out.println(name+"今天的作业太多了,不是很开心");}
}
class Teacher extends Person{public int wages;public Teacher(String name,int age,int wages){super(name,age);this.wages = wages;System.out.println("Teacher(String name,int age,int wages");}
}public class Test {public static void main(String[] args) {Student s1 = new Student("Lihua",21,150);// p1引用指向了s1Person p1 = s1;// p1.mark; // error 无法访问,因为Person中没有mark这个属性// 这里编译的时候编译器认为是访问的Person类中的fun(),但是// 程序运行的时候访问的是子类Student中的fun()// 此过程成为动态绑定s1.fun();}
}
这里要补充动态绑定和静态绑定两个概念。
静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。
下面代码就是向上转型的三种使用场景,请看:
class Person{public String name;public int age;Person(String name,int age){this.name = name;this.age = age;System.out.println("Person(String name,int age)");}public void fun(){System.out.println(name+",你今天开不开心");}
}
class Student extends Person {public int mark;public Student(String name,int age,int mark){super(name,age);this.mark = mark;System.out.println("Student(String name,int age,int mark)");}@Overridepublic void fun(){System.out.println(name+"今天的作业太多了,不是很开心");}
}
class Teacher extends Person{public int wages;public Teacher(String name,int age,int wages){super(name,age);this.wages = wages;System.out.println("Teacher(String name,int age,int wages)");}public void fun(){System.out.println(name+"很开心,因为今天发工资了");}
}public class Test {public static void function(Person p){p.fun();}// 向上转型方式三:返回任意子类对象public static Person function3(){return new Teacher("Simon",21,120);}public static void main(String[] args) {// 向上转型方式一:直接赋值(子类对象直接赋值给父类对象)// Person p1 = new Student("Amy",22,99);// 向上转型方式二:方法的传参过程中,也可以向上转型Student s = new Student("Sam",23,25);function(s);Teacher t = new Teacher("Tom",26,10000);function(t);}
}
运行结果如下:
解释:在function(Person p)方法中,虽然一个引用调用一个方法,但是因为引用所引用的对象不同,导致调用这个方法所表现的行为不同。这种思想就是多态。
下面是向上转型的优缺点:
优点:让代码实现更简单灵活。
缺点::不能调用到子类特有的方法。
4.2向下转型
重要的事情放前面,向下转型是非常不安全的,所以建议平时不要使用向下转型。
示例一:
class Person{public String name;public int age;Person(String name,int age){this.name = name;this.age = age;System.out.println("Person(String name,int age)");}public void fun(){System.out.println(name+",你今天开不开心");}
}
class Student extends Person {public int mark;public Student(String name,int age,int mark){super(name,age);this.mark = mark;System.out.println("Student(String name,int age,int mark)");}public void getScore(){System.out.println("今天出成绩了");}@Overridepublic void fun(){System.out.println(name+"今天的作业太多了,不是很开心");}}
class Teacher extends Person{public int wages;public Teacher(String name,int age,int wages){super(name,age);this.wages = wages;System.out.println("Teacher(String name,int age,int wages)");}public void getWages(){System.out.println("今天发工资哈!");}public void fun(){System.out.println(name+"很开心,因为今天发工资了");}
}public class Test {public static void main(String[] args) {Person p1 = new Student("Donghua",21,112);// p1.getScore //error 因为这里只能访问Person类自己特有的方法Student s1 = (Student)p1;s1.getScore(); //这里通过s1可以访问getScore方法}
}
这里把Person类型强转为子类Student类型。
示例二:向下转型是指将父类类型的引用转换为子类类型的引用。在向下转型的过程中,需要确保原始对象的实际类型是转换后的子类类型,否则会抛出ClassCastException异常。
请看代码:
class Person{public String name;public int age;Person(String name,int age){this.name = name;this.age = age;System.out.println("Person(String name,int age)");}public void fun(){System.out.println(name+",你今天开不开心");}
}
class Student extends Person {public int mark;public Student(String name,int age,int mark){super(name,age);this.mark = mark;System.out.println("Student(String name,int age,int mark)");}public void getScore(){System.out.println("今天出成绩了");}@Overridepublic void fun(){System.out.println(name+"今天的作业太多了,不是很开心");}}
class Teacher extends Person{public int wages;public Teacher(String name,int age,int wages){super(name,age);this.wages = wages;System.out.println("Teacher(String name,int age,int wages)");}public void getWages(){System.out.println("今天发工资哈!");}public void fun(){System.out.println(name+"很开心,因为今天发工资了");}
}public class Test {public static void main(String[] args) {Person p1 = new Student("Jame",21,115);Teacher t1 = (Teacher)p1;t1.getWages();}
}
示例二运行结果如下:
示例二解释:首先创建了一个Student对象,并将其赋值给了一个Person类型的变量p1。这是一种向上转型的操作,可以安全地进行,因为Student是Person的子类。
接着,尝试将p1向下转型为Teacher类型,即将其赋值给一个Teacher类型的变量t1。这是一种不安全的操作,因为p1实际上是Student类型的对象。运行这段代码会抛出ClassCastException异常。
示例二解决方式,请看代码:
Person p1 = new Student("Jame", 21, 115);
if (p1 instanceof Teacher) {Teacher t1 = (Teacher) p1;t1.getWages();
}
else {System.out.println("p1不是Teacher类型的对象");
}
好了,以上就是本文的全部内容啦,就到这里吧!!!
再见啦友友们!!!
相关文章:

【Java基础篇 | 面向对象】--- 聊聊什么是多态(上篇)
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习JavaSE的一点学习心得,欢迎大家在评论区讨论💌 目录 一、什么是多态二、多…...
如何使用 Node.js和Express搭建服务器?
如何使用NodeJs搭建服务器 1. 准备工作1.1 安装Node.js 2. 安装express2.1 初始化package.json2.2 安装express2.3 Express 应用程序生成器 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段…...

帮公司面试了个要25K的测试,我问了他这些问题...
深耕IT行业多年,我们发现,对于一个程序员而言,能去到一线互联网公司,会给我们以后的发展带来多大的影响。 很多人想说,这个我也知道,但是进大厂实在是太难了,简历投出去基本石沉大海࿰…...

Matlab之创建空数组的多种方法汇总
一、matlab空数组是什么? 在MATLAB中,空数组是指没有元素的数组对象。它可以用于占位或者作为容器,等待后续添加元素。 二、创建空数组的多种方法 1、使用空方括号 [] 创建空矩阵 A []; % 创建一个空双精度矩阵 B logical([]); % 创建一…...

HTML实现移动端布局与页面自适应
我们所说的布局方式,这里我们通常指的是width和height在不同页面情况下面的改变。 常见页面的布局方式有 静态布局 (px布局,就是固定其高宽,不论页面怎样放大缩小,其占领的依旧是,使用px固定了的高宽&…...

CSS3技巧36:backdrop-filter 背景滤镜
CSS3 有 filter 滤镜属性,能给内容,尤其是图片,添加各种滤镜效果。 filter 滤镜详见博文:CSS3中强大的filter(滤镜)属性_css3滤镜_stones4zd的博客-CSDN博客 后续,CSS3 又新增了 backdrop-filter 背景滤镜。 backdr…...

【计算机网络】传输层协议——TCP(上)
文章目录 TCPTCP协议段格式报头和有效载荷如何分离?4位首部长度 TCP可靠性确认应答机制的提出序号和确认序号为什么序号和确认序号在不同的字段? 16位窗口大小 6个标志位标志位本质具体标志位PSHRSTURG 超时重传机制 文章目录 TCPTCP协议段格式报头和有效…...

GO语言网络编程(并发编程)Goroutine池
GO语言网络编程(并发编程)Goroutine池 1. Goroutine池 1.1.1. worker pool(goroutine池) 本质上是生产者消费者模型可以有效控制goroutine数量,防止暴涨需求: 计算一个数字的各个位数之和,例…...

C++面试/笔试准备,资料汇总
文章目录 后端太卷,建议往嵌入式,qt,测试,音视频,C一些细分领域投简历。有任何疑问评论区聊,我看到了回复 C面试/笔试准备,资料汇总自我介绍项目实习尽可能有1.编程语言:一.熟悉C语言…...

【Unity3D】UI Toolkit数据动态绑定
1 前言 本文将实现 cvs 表格数据与 UI Toolkit 元素的动态绑定。 如果读者对 UI Toolkit 不是太了解,可以参考以下内容。 UI Toolkit简介UI Toolkit容器UI Toolkit元素UI Toolkit样式选择器UI Toolkit自定义元素 本文完整资源见→UI Toolkit数据动态绑定。 2 数据…...
微信小程序如何在切换页面后原页面状态不变
在微信小程序中,如果要实现在切换页面后原页面状态不变,可以通过以下几种方式来实现: 使用全局数据:可以将需要保持状态的数据存储在小程序的全局数据中,这样无论切换到哪个页面,都可以通过全局数据来获取…...
蓝桥杯官网填空题(生成树)
问题描述 下面是一个 8 个结点的无向图的邻接矩阵表示,其中第 i 行第 j 列表示结点 i 到结点 j 的边长度。当 长度为 0 时表示不存在边。 0 9 3 0 0 0 0 99 0 8 1 4 0 0 03 8 0 9 0 0 0 00 1 9 0 3 0 0 50 4 0 3 0 7 0 60 0 0 0 7 0 5 20 0 0 0 0 5 0 49 0 0 5 6 2…...

Qt Designer UI设计布局小结
目录 前言1 居中布局2 左右布局3 上下布局4 复杂页面布局总结 前言 本文总结了在开发Qt应用程序时使用 Designer 进行UI布局的一些心得体会。Qt Designer是Qt提供的一个可视化界面设计工具,旨在帮助开发人员快速创建和布局用户界面。它提供了丰富的布局管理器和控件…...

linux设备树节点添加新的复位属性之后设备驱动加载异常问题分析
linux设备树节点添加新的复位属性之后设备驱动加载异常问题分析 1 linux原始设备驱动信息1.1 设备树节点信息1.2 linux设备驱动1.3 makefile1.4 Kconfig1.5 对应的defconfig文件 2 修改之后的linux设备驱动2.1 修改之后的设备树节点信息2.2 原始test_fw.c出现的问题以及原因分析…...

连nil切片和空切片一不一样都不清楚?那BAT面试官只好让你回去等通知了。
连nil切片和空切片一不一样都不清楚?那BAT面试官只好让你回去等通知了。 问题 package mainimport ("fmt""reflect""unsafe" )func main() {var s1 []ints2 : make([]int,0)s4 : make([]int,0)fmt.Printf("s1 pointer:%v, s2 p…...

前端构建工具 webpack 笔记
1、了解 webpack 1、定义:本质上,webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具,当 webpack 处理应用它会在内部从一个或多个入口点构建一个依赖图(dependency graph),然后将你项目中所程序时,需的…...

.Net MVC 使用Areas后存在相同Controller时报错的解决办法; 从上下文获取请求的Area名及Controller名
先来说个额外的问题:如何在请求上下文(比如过滤器的中)获取请求对应的Area和Controller 名字?(假设请求上下文对象为 filterContext ): 1. 获取Area名: (string)filterContext.RouteData.DataTo…...
docker-compose部署etcd集群
1. docker-compose.yml cat > docker-compose.yml << EOF version: "3.0"networks:etcd-net: # 网络driver: bridge # 桥接模式volumes:etcd1_data: # 挂载到本地的数据卷名driver: localetcd2_data:driver: localetcd3_data:driver:…...

微信怎么定时发圈?
定时发圈的妙用 在合适的时间点发布新的产品、促销活动,不仅能够及时提醒用户品牌的存在,还可以引发用户的兴趣,增加品牌的曝光率。 选择最佳的发朋友圈时间段,以确保推广内容得到最大的曝光和关注,提高广告投放的效果…...

记录造数据测试接口
一、前言 在java开发中经常需要造数据进行测试接口,这里记录一下常用的通过造数据测试接口的方法。 二、一般的接口传参方式 1、接口的方式最好是使用JSON或者map的方式,这样的好处是传参可以灵活伸缩,返回的结果也最好是JSON或者map的方式…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...