当前位置: 首页 > news >正文

【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行业多年,我们发现,对于一个程序员而言,能去到一线互联网公司,会给我们以后的发展带来多大的影响。 很多人想说,这个我也知道,但是进大厂实在是太难了,简历投出去基本石沉大海&#xff0…...

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:…...

微信怎么定时发圈?

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

记录造数据测试接口

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

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...

SQL进阶之旅 Day 22:批处理与游标优化

【SQL进阶之旅 Day 22】批处理与游标优化 文章简述&#xff08;300字左右&#xff09; 在数据库开发中&#xff0c;面对大量数据的处理任务时&#xff0c;单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”&#xff0c;深入探讨如何通过批量操作和游标技术提…...

6.9本日总结

一、英语 复习默写list11list18&#xff0c;订正07年第3篇阅读 二、数学 学习线代第一讲&#xff0c;写15讲课后题 三、408 学习计组第二章&#xff0c;写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语&#xff1a;复习l默写sit12list17&#…...

循环语句之while

While语句包括一个循环条件和一段代码块&#xff0c;只要条件为真&#xff0c;就不断 循环执行代码块。 1 2 3 while (条件) { 语句 ; } var i 0; while (i < 100) {console.log(i 当前为&#xff1a; i); i i 1; } 下面的例子是一个无限循环&#xff0c;因…...

《架构即未来》笔记

思维导图 第一部分&#xff1a;可扩展性组织的人员配置 第二部分&#xff1a;构建可扩展的过程 第三部分&#xff1a;可扩展的架构方案 第四部分&#xff1a;其他的问题和挑战 资料 问软件工程研究所&#xff1a; https://www.sei.cmu.edu/ AKF公司博客: http://www.akfpart…...

ubuntu2404 gpu 没接显示器,如何保证远程显示的分辨率

1. 使用 xserver-xorg-video-dummy 创建虚拟显示器 如果系统在无物理显示器连接时无法识别显示输出&#xff0c;可以使用 xserver-xorg-video-dummy 驱动程序创建虚拟显示器。以下是设置步骤&#xff1a; 安装虚拟显示器驱动程序&#xff1a; sudo apt install xserver-xorg-v…...

vb监测Excel两个单元格变化,达到阈值响铃

需求 在Excel中实现监控两个单元格之间的变化范围&#xff0c;当达到某个设定的值的范围内时&#xff0c;实现自动响铃提示。 实现&#xff1a; 首先设置Excel&#xff0c;开启宏、打开开发者工具&#xff0c;点击visual Basic按钮&#xff0c;然后在左侧双击需要监测的shee…...