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

java--多态(详解)

目录

  • 一、概念
  • 二、多态实现的条件
  • 三、向上转型和向下转型
    • 3.1 向上转型
    • 3.2 向下转型
  • 四、重写和重载
  • 五、理解多态
    • 5.1练习:
    • 5.2避免在构造方法中调用重写的方法:

                           欢迎来到权权的博客~欢迎大家对我的博客提出指导

这是我的博客主页:点击

一、概念

通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态。

在这里插入图片描述

二、多态实现的条件

在java中要实现多态,必须要满足如下几个条件,缺一不可:

  1. 必须在继承体系下
  2. 子类必须要对父类中方法进行重写
  3. 通过父类的引用调用重写的方法

三、向上转型和向下转型

3.1 向上转型

在这里插入图片描述
三种向上转型的方式:
在这里插入图片描述


1.直接赋值

  Animals animals=new Dog("小狗",6);

2.方法的传参

  public static void func(Animals animal){}public static void main(String[] args) {Dog dog=new Dog("x",6);func(dog);}

3.返回值

    public static Animals func2(){Dog dog=new Dog("x",56);return dog;}public static void main(String[] args) {Animals animals=func2();}
}

缺点:通过父类的引用不能调用子类的方法
在这里插入图片描述


3.2 向下转型

在这里插入图片描述

向下转型无非就是把一个父类引用放着子类对象,然后强转成对应的子类类型在赋值给子类引用,也就是将父类引用还原成子类对象。

class TestAnimal {public static void main(String[] args) {//向下转型 -> 不安全//instanceof 判断animal引用的对象是不是Dog类型的,如果是则为 true 不是则为 falseAnimal animal = new Dog("王五", 12);if (animal instanceof Dog) {Dog dog = (Dog)animal;dog.eat();}}
}

四、重写和重载

重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。

【方法重写的规则】:

子类在重写父类的方法时,一般必须与父类方法原型一致:返回值类型方法名 (参数列表) 要完全一致被重写的方法返回值类型可以不同,但是必须是具有父子关系的。
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected父类被static、private修饰的方法、构造方法都不能被重写。
重写的方法, 可以使用@Override注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.


在这里插入图片描述


在子类中对父类的方法进行重写
在这里插入图片描述
在这里插入图片描述


方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

public class TestMethod {
public static void main(String[] args) {
add(1, 2); // 调用add(int, int)
add(1.5, 2.5); // 调用add(double, double)
add(1.5, 2.5, 3.5); // 调用add(double, double, double)
}
public static int add(int x, int y) {
return x + y;
}
public static double add(double x, double y) {
return x + y;
}
public static double add(double x, double y, double z) {
return x + y + z;
}
}

【重写和重载的区别】
在这里插入图片描述

在这里插入图片描述


五、理解多态

在这里插入图片描述
可以看到animals引用的对象是不一样的,但是调用的是同一个方法,此时表现出的不同现象我们叫做多态。


5.1练习:

打印指定不同图案(多态实现):

public class Drawing {public void draw() {System.out.println("画图");}
}
class DrawCircle extends Drawing {@Overridepublic void draw() {System.out.print("⚪");}
}
class DrawFlower extends Drawing {@Overridepublic void draw() {System.out.print("❀");}
}
class DrawTriangle extends Drawing {@Overridepublic void draw() {System.out.print("▲");}
}

第一种方法:用 for-each语句

class TestDraw {//方法一:使用 循环 + if elsepublic static void draw1() {DrawTriangle triangle = new DrawTriangle();DrawFlower flower = new DrawFlower();DrawCircle circle = new DrawCircle();String[] shapes = {"Triangle", "Flower", "Flower", "Circle", "Flower", "Triangle"};//增强for循环遍历数组for (String s : shapes) {if (s.equals("Triangle")) {triangle.draw();} else if (s.equals("Flower")) {flower.draw();} else if (s.equals("Circle")) {circle.draw();}}}public static void main(String[] args) {draw1();}
}

第二种用多态

class TestDraw {public static void draw2() {Drawing[] shapes = { new DrawTriangle(), new DrawFlower(), new DrawFlower(),new DrawCircle(), new DrawFlower(), new DrawTriangle()};for (Drawing s : shapes) {s.draw();}}public static void main(String[] args) {draw2();}
}

在这里插入图片描述


多态部分的优点:

可以有效降低代码复杂度,避免出现多个 if else可扩展性更强,如果要新增打印,也更简单

多态的缺点:

属性没有多态性,当父类属性和子类属性同名,通过父类引用只能调用父类自己的成员属性构造方法也没有多态性

5.2避免在构造方法中调用重写的方法:

class A {public A() {func();}public void func() {System.out.println("A.func()");}
}
class B extends A {private int num = 1;@Overridepublic void func() {System.out.println("B.func() " + num);}
}
public class Test {public static void main(String[] args) {A b = new B();}
}

可以看到构造 D 对象的同时, 会调用 B 的构造方法。
B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func此时 D >对象自身还没有构造, 此时 num 处在未初始化的状态, 值为 0.。
如果具备多态性,num的值应该是1.所以在构造函数内,尽量避免使用实例方法,除了final和private方法。

结论: “用尽量简单的方式使对象进入可工作状态”, 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题。

在这里插入图片描述

欧耶!!!我学会啦!!!

相关文章:

java--多态(详解)

目录 一、概念二、多态实现的条件三、向上转型和向下转型3.1 向上转型3.2 向下转型 四、重写和重载五、理解多态5.1练习:5.2避免在构造方法中调用重写的方法: 欢迎来到权权的博客~欢迎大家对我的博客提出指导这是我的博客主页:点击 一、概念…...

windows DLL技术-DLL概述

动态链接库 (DLL) 是一个模块,其中包含可由另一个模块 (应用程序或 DLL) 使用的函数和数据。 DLL 可以定义两种类型的函数:导出函数和内部函数。 导出的函数旨在由其他模块调用,以及从定义它们的 DLL 中调用。 内部函数通常只能从定义内部函…...

C++ —— 实现一个日期类

目录 一. 对日期类的介绍 二. 实现日期类 1. 运算符重载 2.日期类实现代码 一. 对日期类的介绍 通过对类和对象(这里链接是类和对象的介绍)的学习,类就是一种模型一样的东西,是对象一种抽象的描述。所以实现日期类&#xff0…...

Java全栈经典面试题剖析5】JavaSE高级 -- 集合

目录 面试题3.18 Java中有多少种数据结构,分别是什么? 面试题3.19 List、Set和Map的区别? 面试题3.20 List遍历方式有多少种 面试题3.21 Arraylist,Vector和Linkedlist 的区别 面试题3.22 Collection和Collections的区别 面试…...

python中如何获取对象信息

目录 一、获取对象类型 二、使用isinstance()函数 三、使用dir()函数 四、使用对象的__dict__属性(适用于大多数自定义对象) 五、使用文档字符串(__doc__属性)获取对象的文档信息 一、获取对象类型 使用type()函数&#xff…...

逐行讲解transformers中model.generate()源码

目录 简介输入程序model.generate()输入参数1. 创建生成参数对象 generation_config2. 初始化部分输入参数3. 定义模型输入4. 定义其他模型参数5. 准备 input_ids6. 准备 max_length7. 确定生成模式8. 准备 logits 处理器9. 准备 stopping 处理器10. 执行生成 self._sample1. 先…...

小白对时序数据库的理解

一、什么是时序数据库? 时序数据库(Time Series Database,TSDB)是一种专门用于存储、处理和分析时间序列数据的数据库管理系统。时间序列数据是按时间顺序记录的数据,通常由各种设备和传感器生成,例如智慧…...

打开游戏提示丢失(或找不到)XINPUT1_3.DLL的多种解决办法

xinput1_3.dll是一个动态链接库(DLL)文件,它在Windows操作系统中扮演着重要的角色。该文件作为系统库文件,通常存放于C:\Windows\System32目录下(对于32位系统)或C:\Windows\SysWOW64目录下(对于…...

netty的网络IO模型

参考: 聊聊Netty那些事儿之从内核角度看IO模型...

电子木鱼小游戏小程序源码系统 带完整的安装代码包以及搭建部署教程

系统概述 在快节奏的生活中,人们越来越注重内心的平静与放松。电子木鱼小游戏小程序正是基于这一需求而诞生的,它将传统的木鱼文化与现代科技相结合,为用户提供了一个简单、方便、有趣的冥想与放松工具。通过敲击屏幕上的虚拟木鱼&#xff0…...

支付域——交易系统设计

摘要 交易是业务流转的基础,其中交易系统和订单系统的设计至关重要。交易系统需确保安全、高效与稳定。在设计时,要考虑支付方式的多样性及兼容性,保障资金流转的准确与安全。同时,应具备良好的风险控制机制,防范欺诈等风险。订单系统则负责记录和管理交易的全过程。需清…...

IBus 和 Fcitx 框架下的rime输入法引擎

Rime 输入法引擎 Rime(中州韵输入法引擎):这是一个跨平台的输入法引擎,支持多种输入法方案,如拼音、五笔、注音等。Rime本身不提供前端界面,它需要与输入法框架(如IBus或Fcitx)结合…...

Java基础-JVM

JVM构成部分 类加载系统 类加载子系统的作用是将磁盘中的.class文件加载到内存当中。工作过程如下: 加载:通过类全路径名获取二进制字节流;将这个二进制字节流代表的数存储构转化为方法区运行时数据结构;在内存生成一个代表该类的…...

集成学习:投票法、提升法、袋装法

集成学习:投票法、提升法、袋装法 目录 🗳️ 投票法 (Voting)🚀 提升法 (Boosting)🛍️ 袋装法 (Bagging) 1. 🗳️ 投票法 (Voting) 投票法是一种强大的集成学习策略,它通过将多个模型的预测结果进行组合…...

波浪理论、江恩理论、价值投资的结合

结合波浪理论、江恩理论和价值投资,需要理解这三种方法的核心原理和应用方式。下面详细解析如何将它们融合在一起,形成一个更全面的投资策略: 1. 基本概述 波浪理论:由艾略特提出,通过分析市场波动的五个上升浪和三个…...

LRDDR4芯片学习(三)——命令和时序

ddr command: activate commandrefresh commandprecharge commandwrite/read commandburst write/read commandMRR/MRW command 一、Activate命令 在读写命令之前,必须要发送Activate命令,由ACTIVATE-1、ACTIVATE-2命令组成。ACTIVATE命令中包含了BA[…...

【趣学C语言和数据结构100例】

【趣学C语言和数据结构100例】 问题描述 61.假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可共享相同的后缀存储空间,例如,loading 和 being 的存储映像如下图所示,设 strl 和 str2 分别指向两个单词所在单链表的头结点,链表结点结构为 data next。请设计…...

linux卸载数据库(最为完整的卸载方式)

1.首先检查是否安装了MySQL组件 我们可以看到有五个与mysql相关的组件 2.卸载前关闭MySQL服务 systemctl stop mysqld systemctl status mysqld 3.收集MySQL对应的文件夹信息 whereis mysql 4.卸载删除MySQL各类组件 #例如 rpm -ev --nodeps mysql-community-libs-5.7.…...

H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布)

LUA脚本的好处是用户可以根据自己注册的一批API(当前TOOL已经提供了几百个函数供大家使用),实现各种小程序,不再限制Flash里面已经下载的程序,就跟手机安装APP差不多,所以在H7-TOOL里面被广泛使用&#xff…...

使用梧桐数据库进行销售趋势分析和预测

在当今竞争激烈的商业环境中,企业需要深入了解销售数据,以便做出明智的决策。销售趋势分析和预测是帮助企业把握市场动态、优化库存管理、制定营销策略的重要工具。本文将介绍如何使用SQL来创建销售数据库的表结构,插入示例数据,并…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

从零开始了解数据采集(二十八)——制造业数字孪生

近年来&#xff0c;我国的工业领域正经历一场前所未有的数字化变革&#xff0c;从“双碳目标”到工业互联网平台的推广&#xff0c;国家政策和市场需求共同推动了制造业的升级。在这场变革中&#xff0c;数字孪生技术成为备受关注的关键工具&#xff0c;它不仅让企业“看见”设…...

npm安装electron下载太慢,导致报错

npm安装electron下载太慢&#xff0c;导致报错 背景 想学习electron框架做个桌面应用&#xff0c;卡在了安装依赖&#xff08;无语了&#xff09;。。。一开始以为node版本或者npm版本太低问题&#xff0c;调整版本后还是报错。偶尔执行install命令后&#xff0c;可以开始下载…...

RabbitMQ work模型

Work 模型是 RabbitMQ 最基础的消息处理模式&#xff0c;核心思想是 ​​多个消费者竞争消费同一个队列中的消息​​&#xff0c;适用于任务分发和负载均衡场景。同一个消息只会被一个消费者处理。 当一个消息队列绑定了多个消费者&#xff0c;每个消息消费的个数都是平摊的&a…...