【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类型的对象");
}

好了,以上就是本文的全部内容啦,就到这里吧!!!
再见啦友友们!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构基础7:二叉树【链式结构】实现和递归思想。

二叉树的链式结构实现 一.二叉树链式结构的实现:1.前置说明:1.创建二叉树:2.二叉树的结构: 2.二叉树的遍历:1.二叉树的前中后序遍历:2.内容拓展: 二.二叉树链式(题目)题目一:计算节点…

小程序源码:多功能口袋工具箱微信小程序源码-带流量主|云开发(更新)

这里主要分享多功能口袋工具箱微信小程序源码,有带流量主,而且超多功能工具箱组合的微信小程序源码。无需服务器即可搭建,可以设置流量主赚取收益。 源码链接: 网盘源码 密码:hma8 工具箱的应用一览: 1…

【计算机网络】传输层协议——TCP(上)

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

Qt Designer UI设计布局小结

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

我的个人网站——宏夏Coding上线啦

网站地址:宏夏Coding Github地址:🔥🔥宏夏coding网站,致力于为编程学习者、互联网求职者提供最需要的内容!网站内容包括求职秘籍,葵花宝典(学习笔记),资源推…

线性代数的学习和整理20,关于向量/矩阵和正交相关,相似矩阵等(草稿)

目录 1 什么是正交 1.1 正交相关名词 1.2 正交的定义 1.3 正交向量 1.4 正交基 1.5 正交矩阵的特点 1.6 正交矩阵的用处 1 什么是正交 1.1 正交相关名词 orthogonal set 正交向量组正交变换orthogonal matrix 正交矩阵orthogonal basis 正交基orthogonal decompositio…

访问局域网内共享文件时报错0x80070043,找不到网络名

我是菜鸡 此篇只为分享一个我遇到的很简单的但是排查了好久的小问题。 我的网络环境是在校园网内, 自己的办公电脑设置了固定IP:10.11.128.236,同事电脑IP为:10.11.128.255 本人需要访问同事在局域网内分享的文件,…

关于vscode的GitLens插件里的FILE HISTORY理解

最近在用vscode的GitLens插件开发项目遇到这个疑问,先看图: 每当我点击FILE HISTORY 一个commit时,正常来说显示器会自动将点击的提交版本和它上一个提交版本进行比较,如果单纯这么理解的话就错了,因为GitLens的File …

富斯I6刷10通道固件

使用USB转串口模块刷写10通道固件 一、下载固件 1. 十通道英文固件 下载地址: https://github.com/benb0jangles/FlySky-i6-Mod-/tree/master 选择 FlySky-i6-Mod–master \ 10ch Mod i6 Updater \ 10ch_MOD_i6_Programmer_V1 路径下的文件,亲测可用。 2. 原版六通道中…

Android性能优化之应用瘦身(APK瘦身)

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读二、概览2.1 apk组成 三、优化方向3.1 源代码3.1.1 代码混…

网站搭建从零开始(0)--域名的选择与解析

目录 确定用途 购买域名 使用可靠的注册商购买域名 想好域名关键词 检查域名是否可用 添加域名到购物车并完成购买 域名的解析 登录注册商账户 选择要配置的域名 进入DNS解析设置 添加DNS记录 保存配置 检查解析是否生效 提示 确定用途 在购买域名之前&#xf…

【MFC】Button控件美化(自绘)

在MFC中Button控件不能通过OnCtlColor()函数对外观做太多的改变。 HBRUSH C按钮控件自绘Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {HBRUSH hbr CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);switch (pWnd->GetDlgCtrlID()){case ID…

Dinky上路之旅

1、部署flink集群 1.1、flink-conf.yaml cat > flink-conf.yaml << EOF jobmanager.rpc.address: boshi-146 jobmanager.rpc.port: 6123 jobmanager.bind-host: 0.0.0.0 jobmanager.memory.process.size: 1600m taskmanager.bind-host: 0.0.0.0 # 修改为本机ip tas…

芯科蓝牙BG27开发笔记1-新建示例工程

此笔记的必要性 芯科的官方资料很丰富&#xff0c;并且ssv5中能方便索引到所需文档&#xff0c;不过大而全的问题就是找不到合适的切入点&#xff0c;更不会有本地化比较好的中文的系统的教程了。往往看到一个starting guide&#xff0c;会延伸其他starting guide&#xff0c;…

自动化控制系统的设计重点是什么?

要实现对选择性激光烧结系统预热温度的控制&#xff0c;需要找到合理的控制对象模型&#xff0c;但选择性激光烧结设备的预热温度场是一个复杂的非线性系统&#xff0c;很难找到合理的控制对象模型来实现预热温度场的温度控制。模糊控制不需要具体的控制模型&#xff0c;预热温…

如何修改jupyter notebook默认打开路径

1、用jupyter notebook在其他位置打开自己的ipython项目&#xff1a; jupyter notebook是一个很好用的工具&#xff0c;可以保存运行结果&#xff0c;还可以给项目添加很多可视化操作与介绍文字。安装anaconda后&#xff0c;jupyter notebook就会自动安装&#xff0c;点开它会…

The specified module could not be found.

新电脑运行项目的时候出现了某个包找不到的问题 \\?\D:\guanwnag\cloudquery-website\node_modules\.pnpm\nxnx-win32-x64-msvc16.5.3\node_modules\nx\nx-win32-x64-msvc\nx.win32-x64-msvc.node 引入的路径就感觉有问题 去github上查找原因&#xff0c;发现是没安装 Micro…

基于SSM的应急资源管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

TypeScript类型推断

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 类型推断 1. 基础类型推断 #2. 最佳公共类型推断 3. 上下文类型推断 4. 类型断言 #5. 类型推断和泛型 总结 类…

第1章_瑞萨MCU零基础入门系列教程之单片机程序的设计模式

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…