【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的方式…...
Azure AI实战:从Demo到生产级智能应用架构全解析
1. 项目概述与核心价值最近在探索Azure AI服务时,我偶然发现了一个名为“Azure-AIGEN-demos”的GitHub仓库。这个项目由开发者retkowsky维护,乍一看名字,你可能会觉得它又是一个普通的Azure AI示例代码合集。但当我真正深入进去,花…...
从Siri上车看车载语音交互:技术演进、产业融合与安全设计
1. 项目概述:当Siri首次驶入驾驶舱2012年洛杉矶国际车展上的一则新闻,在当时的汽车与科技圈激起了不小的涟漪。通用汽车宣布,其旗下的雪佛兰品牌将成为首批将苹果Siri语音助手集成到车载信息娱乐系统中的汽车制造商,首发车型包括雪…...
飞蜂窝技术:从概念到5G室内覆盖核心的实战演进
1. 从“未来可期”到“正在爆发”:飞蜂窝技术的十年之约在通信行业里待久了,你总会听到一些技术名词被反复提起,它们像流星一样划过天际,被分析师们预言将“改变一切”,然后……似乎又沉寂了下去。飞蜂窝(F…...
ARM架构TRFCR_EL2寄存器详解与虚拟化调试实践
1. ARM架构中的TRFCR_EL2寄存器概述在ARMv8/v9架构中,TRFCR_EL2(Trace Filter Control Register at EL2)是一个关键的系统寄存器,专门用于在Hypervisor(EL2)级别控制处理器的跟踪功能。作为ARM CoreSight调…...
AI辅助开发工作流:用免费代理优化付费工具,提升代码生成效率
1. 项目概述:用免费AI代理优化付费AI工具的开发工作流如果你和我一样,订阅了Claude Pro或者GitHub Copilot,但每个月看着额度条飞速见底,心里总有点发慌,那这篇文章就是为你准备的。我们不是在讨论哪个AI写代码更强&am…...
Python内置模块:io、file、json、csv
一、io StringIO - 文本字符串的缓冲区 from io import StringIO# 创建StringIO对象 sio StringIO() # 空缓冲区 sio StringIO("initial text") # 带初始数据# 常用方法 sio.write("Hello ") # 写入字符串&…...
构建AI智能体技能超市:标准化工作流与多平台适配实践
1. 项目概述:一个面向AI智能体的“技能超市”如果你和我一样,每天都在和Codex、Claude、Cursor这些AI助手打交道,那你肯定也遇到过这样的场景:想让AI帮你生成一份规范的Git提交信息、自动更新文档索引,或者为一个新项目…...
开源状态监控工具openclaw-status:从原理到部署的完整实践指南
1. 项目概述:一个开源状态监控工具的诞生最近在折腾一个开源项目,叫openclaw-status,是vibe-with-me-tools组织下的一个子项目。简单来说,这是一个用于监控和展示各种服务、应用、设备状态的工具。听起来是不是有点像那些商业化的…...
Linux端口转发到外网完全教程:iptables DNAT+SNAT实现内网服务暴露
一、什么是外网端口转发Linux端口转发到外网,是指将Linux服务器上某个端口的流量,转发到外网(公网)的另一台服务器。这样做的典型场景是:你有一台内网服务器没有公网IP,但另一台海外服务器有公网IP…...
浏览器缓存揭秘:它什么时候“自动”生效?
🚀 浏览器缓存揭秘:它什么时候“自动”生效? 🤔 什么是浏览器缓存? 简单来说,浏览器缓存就是浏览器把下载过的资源(HTML, CSS, JS, 图片等)保存在本地硬盘或内存中。当再次请求相同…...

