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

Java多态详解(2)

向上转型和向下转型

向上转型

定义:实际就是创建一个子类对象,将其当作父类对象来使用

语法格式:父类类型 对象名 = new 子类类型()

Animal animal = new Cat("元宝", 2);

animal是父类类型,但是可以引用子类对象,因为是从小范围到大范围的转换。

特点:

  1. 编译时多态性: 父类引用变量可以引用子类对象,编译器会在编译时检查引用变量的类型是否与对象的类型兼容。

  2. 运行时多态性: 在运行时,根据引用变量所指向的实际对象类型来调用对应的方法,实现方法的多态性。

  3. 限制方法访问: 向上转型后,只能调用父类中声明的方法,而不能直接调用子类新增的方法。

使用场景:1.直接赋值 2.方法传参 3.方法返回

举例一:直接赋值:

class Animal {void makeSound() {System.out.println("Animal makes a sound");}
}class Dog extends Animal {void makeSound() {System.out.println("Dog barks");}
}public class Main {public static void main(String[] args) {Animal animal = new Dog(); // 直接赋值animal.makeSound(); // 调用的是 Dog 类的方法}
}

举例二:方法传参

class Shape {void draw() {System.out.println("draw a shape");}
}class Circle extends Shape {@Overridevoid draw() {System.out.println("draw a circle");}
}class Triangle extends Shape {@Overridevoid draw() {System.out.println("draw a triangle");}
}
public class Test {public static void shapeDrawing(Shape s) {s.draw();}public static void main(String[] args) {Shape s1 = new Circle();Shape s2 = new Triangle();shapeDrawing(s1);shapeDrawing(s2);//方法传参,传递不同子类对象}
}

举例三:做返回值

class Vehicle {String getType() {return "Vehicle";}
}class Car extends Vehicle {@OverrideString getType() {return "Car";}
}class Bike extends Vehicle {@OverrideString getType() {return "Bike";}
}public class Test {public static Vehicle getType(String type){if(type.equals("car")){return new Car();} else if(type.equals("bike")) {return new Bike();} else {return new Vehicle();}}public static void main(String[] args) {Vehicle v1 = getType("car");Vehicle v2 = getType("bike");Vehicle v3 = getType("plane");System.out.println(v1.getType());System.out.println(v2.getType());//方法返回,返回的实际上可能是子类对象System.out.println(v3.getType());}
}

向上转型的优点:让代码实现更加简单灵活

向上转型的缺点:不能调用到子类特有的方法

向下转型

将一个子类对象经过向上转型之后当作父类方法使用,在无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用还原为子类对象即可,即向下转换。

class Animal1 {void makeSound() {System.out.println("Animal makes a sound");}
}class Dog1 extends Animal1 {@Overridevoid makeSound() {System.out.println("Dog barks");}void fetch() {System.out.println("Dog fetch the ball");}
}public class Test1 {public static void main(String[] args) {Animal1 animal1 = new Dog1();//向上转型//向下转型if(animal1 instanceof Dog1) {Dog1 dog = (Dog1)animal1;//实例类型检查和向下转型dog.makeSound();//调用子类的方法dog.fetch();//调用子类特有的方法}}
}

向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛出异常。Java中为了提高向下转型的安全性,引入了instanceof(用于检查一个对象是否是指定类或其子类的实例),如果表达式的结果为true,则可以安全转换。

多态的优缺点

优点

假设有如下代码:

class Shape {//属性。。。public void draw() {System.out.println("画图形");}
}class Rect extends Shape {@Overridepublic void draw() {System.out.println("⎕");}
}class Circle extends Shape {@Overridepublic void draw() {System.out.println("◉");}
}class Star extends Shape {@Overridepublic void draw() {System.out.println("★");}
}

1.能够降低代码的“圈复杂度”,避免使用大量的if-else

圈复杂度:一种描述一段代码复杂程度的方式。一段代码如果平铺直叙,那么就比较简单容易理解,而如果有很多条件分支或者循环语句,就认为了解起来比较复杂。

因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数,这个个数就称为“圈复杂度”,如果一个方法的圈复杂度太高,就需要考虑重构

不同公司对于圈复杂度的规范不一样,但一般不会超过10

例如我们现在需要的不只是打印一个形状了,而是多个形状,如果不基于多态,实现代码如下:

public static void drawShapes() {Rect rect = new Rect();Circle circle = new Circle();Star star = new Star();String[] shapes = {"circle", "rect", "circle", "rect", "star"};for(String shape : shapes) {if(shape.equals("circle")){circle.draw();} else if(shape.equals("rect")) {rect.draw();} else if(shape.equals("star")) {star.draw()}}}

如果使用多态,则不必写这么多的if-else分支语句,代码更简单。

Shape[] shapes = {new Circle(), new Rect(), new Circle(), new Rect(), new Star()};
for(Shape shape : shapes) {shape.draw();
}

2.可扩展能力更强

如果要新增一种形状,使用多态的方式代码改动成本也比较低。

class Triangle extends Shape {@Override public void draw() {System.out.println("▲");}
}

对于类的调用者(主函数),只要创建一个新类的实例就可以了,改动成本很低。

而对于不用多态的情况,就要把drawShapes中的if-else进行一定修改,改动成本更高

缺点

代码运行效率降低

1.属性没有多态性:当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性

2.构造方法没有多态性

 

相关文章:

Java多态详解(2)

向上转型和向下转型 向上转型 定义:实际就是创建一个子类对象,将其当作父类对象来使用。 语法格式:父类类型 对象名 new 子类类型() Animal animal new Cat("元宝", 2); animal是父类类型,但是可以引用子…...

Camtasia导入srt字幕乱码

我们在使用camtasia制作视频项目时,有时为了用户体验需要导入srt格式的字幕文件,在操作无误的情况下,一顿操作猛如虎之后字幕顺利的导入到软件中了,但字幕却出现了乱码的现象。如下图所示: 如何解决srt乱码问题呢&…...

YOLOv5、YOLOv8改进:SOCA注意力机制

目录 简介 2.YOLOv5使用SOCA注意力机制 2.1增加以下SOCA.yaml文件 2.2common.py配置 2.3yolo.py配置 简介 注意力机制(Attention Mechanism)源于对人类视觉的研究。在认知科学中,由于信息处理的瓶颈,人类会选择性地关注所有…...

机器人的运动范围

声明 该系列文章仅仅展示个人的解题思路和分析过程,并非一定是优质题解,重要的是通过分析和解决问题能让我们逐渐熟练和成长,从新手到大佬离不开一个磨练的过程,加油! 原题链接 机器人的运动范围https://leetcode.c…...

学习笔记|基于Delay实现的LED闪烁|模块化编程|SOS求救灯光|STC32G单片机视频开发教程(冲哥)|第六集(下):实现LED闪烁

文章目录 2 函数的使用1.函数定义(需要带类型)2.函数声明(需要带类型)3.函数调用 3 新建文件,使用模块化编程新建xxx.c和xxx.h文件xxx.h格式:调用头文件验证代码调用:完整的文件结构如下&#x…...

微服务-Ribbon(负载均衡)

负载均衡的面对多个相同的服务的时候,我们选择一定的策略去选择一个服务进行 负载均衡流程 Ribbon结构组成 负载均衡策略 RoundRobinRule:简单的轮询服务列表来选择服务器AvailabilityFilteringRule 对两种情况服务器进行忽略: 1.在默认情…...

解决C#报“MSB3088 未能读取状态文件*.csprojAssemblyReference.cache“问题

今天在使用vscode软件C#插件,编译.cs文件时,发现如下warning: 图(1) C#报cache没有更新 出现该warning的原因:当前.cs文件修改了,但是其缓存文件*.csprojAssemblyReference.cache没有更新,需要重新清理一下工程&#x…...

GeoScene Pro在地图制图当中的应用

任何地理信息系统建设过程中,背景地图的展示效果对整个系统功能的实现没有直接影响;但是地图的好看与否,会间接的决定着整个项目的高度。 一幅精美的地图不仅能令人赏心悦目、眼前一亮,更能将人吸引到你的系统中,更愿意…...

国标混凝土结构设计规范的混凝土本构关系——基于python代码生成

文章目录 0. 背景1. 代码2. 结果测试 0. 背景 最近在梳理混凝土塔筒的计算指南,在求解弯矩曲率关系以及MN相关曲线时,需要混凝土的本构关系作为输入条件。 1. 代码 这段代码还是比较简单的。不过需要注意的是,我把受拉和受压两种状态统一了…...

系统架构设计-架构师之路(八)

软件架构概述 需求分析到软件设计之间的过渡过程就是软件架构。 需求分析人员整理成文档,但是开发人员对业务并不熟悉,这时候中间就需要一个即懂软件又懂业务的人,架构师来把文档整理成系统里的各个开发模块,布置开发任务。 软…...

【SA8295P 源码分析】25 - QNX Ethernet MAC 驱动 之 emac_isr_thread_handler 中断处理函数源码分析

【SA8295P 源码分析】25 - QNX Ethernet MAC 驱动 之 emac_isr_thread_handler 中断处理函数源码分析 一、emac 中断上半部:emac_isr()二、emac 中断下半部:emac_isr_thread_handler()2.1 emac 中断下半部:emac_isr_sw()系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章…...

函数栈帧的创建与销毁

目录 引言 基础知识 内存模型 ​ 寄存器的种类与功能 常用的汇编指令 函数栈帧创建与销毁 main()函数栈帧的创建 NO1. NO2. NO3. NO4. NO5. NO6. main()函数栈帧变量的创建 调用Add()函数栈帧的预备工作——传参 NO1. NO2. NO3. Add()函数栈帧的创建 …...

工业安全生产平台在面粉行业的应用分享

一、背景介绍 面粉行业是一个传统的工业行业,安全生产问题一直备受关注。然而,由于生产过程中存在的各种安全隐患和风险,如粉尘爆炸、机械伤害等,使得面粉行业的安全生产形势依然严峻。为了解决这一问题,工业安全生产…...

Gitlab服务部署及应用

目录 Gitlab简介 Gitlab工作原理 Gitlab服务构成 Gitlab环境部署 安装依赖包 启动postfix,并设置开机自启 设置防火墙 下载安装gitlab rpm包 修改配置文件/etc/gitlab/gitlab.rb,生产环境下可以根据需求修改 重新加载配置文件 浏览器登录Gitlab输…...

【nodejs】用Node.js实现简单的壁纸网站爬虫

1. 简介 在这个博客中,我们将学习如何使用Node.js编写一个简单的爬虫来从壁纸网站获取图片并将其下载到本地。我们将使用Axios和Cheerio库来处理HTTP请求和HTML解析。 2. 设置项目 首先,确保你已经安装了Node.js环境。然后,我们将创建一个…...

xlsx xlsx-style file-saver 导出json数据到excel文件并设置标题字体加粗

xlsx:用于处理Excel文件。xlsx-style:用于添加样式到Excel文件中。file-saver:用于将生成的Excel文件保存到用户的计算机上 npm install xlsx xlsx-style file-saver// 导入所需库 const XLSX require(xlsx); const XLSXStyle require(xls…...

Win11游戏高性能模式怎么开

1、点击桌面任务栏上的“开始”图标,在打开的应用中,点击“设置”; 2、“设置”窗口,左侧找到“游戏”选项,在右侧的选项中,找到并点击打开“游戏模式”; 3、打开的“游戏模式”中,找…...

深度学习最强奠基作ResNet《Deep Residual Learning for Image Recognition》论文解读(上篇)

1、摘要 1.1 第一段 作者说深度神经网络是非常难以训练的,我们使用了一个残差学习框架的网络来使得训练非常深的网络比之前容易得很多。 把层作为一个残差学习函数相对于层输入的一个方法,而不是说跟之前一样的学习unreferenced functions 作者提供了…...

第22次CCF计算机软件能力认证

第一题&#xff1a;灰度直方图 解题思路&#xff1a; 哈希表即可 #include<iostream> #include<cstring>using namespace std;const int N 610; int a[N]; int n , m , l;int main() {memset(a , 0 , sizeof a);cin >> n >> m >> l;for(int …...

Go语言基础之基本数据类型

Go语言中有丰富的数据类型&#xff0c;除了基本的整型、浮点型、布尔型、字符串外&#xff0c;还有数组、切片、结构体、函数、map、通道&#xff08;channel&#xff09;等。Go 语言的基本类型和其他语言大同小异。 基本数据类型 整型 整型分为以下两个大类&#xff1a; 按…...

Linux Tracing Technologies

目录 1. Linux Tracing Technologies 1. Linux Tracing Technologies Linux Tracing TechnologieseBPFXDPDPDK...

iOS自定义下拉刷新控件

自定义下拉刷新控件 概述 用了很多的别人的下拉刷新控件&#xff0c;想写一个玩玩&#xff0c;自定义一个在使用的时候也会比较有意思。使应用更加的灵动一些&#xff0c;毕竟谁不喜欢各种动画恰到好处的应用呢。 使用方式如下&#xff1a; tableview.refreshControl XRef…...

Springboot写单元测试

导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintag…...

一篇文章教你使用Docker本地化部署Chatgpt(非api,速度非常快!!!)及裸连GPT的方式(告别镜像GPT)

本地搭建ChatGPT&#xff08;非api调用&#xff09; 第一种方法&#xff1a;使用Docker本地化部署第一步&#xff0c;下载安装Docker登录GPT 第二种方法&#xff1a;不部署项目&#xff0c;直接连接 第一种方法&#xff1a;使用Docker本地化部署 这种方法的好处就是没有登录限…...

前馈神经网络dropout实例

直接看代码。 &#xff08;一&#xff09;手动实现 import torch import torch.nn as nn import numpy as np import torchvision import torchvision.transforms as transforms import matplotlib.pyplot as plt#下载MNIST手写数据集 mnist_train torchvision.datasets.MN…...

Android DataStore:安全存储和轻松管理数据

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、使用3.1 Preferences DataStore添加依赖数据读…...

opencv进阶12-EigenFaces 人脸识别

EigenFaces 通常也被称为 特征脸&#xff0c;它使用主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09; 方法将高维的人脸数据处理为低维数据后&#xff08;降维&#xff09;&#xff0c;再进行数据分析和处理&#xff0c;获取识别结果。 基本原理…...

The internal rate of return (IRR)

内部收益率 NPV(Net Present Value)_spencer_tseng的博客-CSDN博客...

半导体自动化专用静电消除器主要由哪些部分组成

半导体自动化专用静电消除器是一种用于消除半导体生产过程中的静电问题的设备。由于半导体制造过程中对静电的敏感性&#xff0c;静电可能会对半导体器件的质量和可靠性产生很大的影响&#xff0c;甚至造成元件损坏。因此&#xff0c;半导体生产中采用专用的静电消除器是非常重…...

【C++入门到精通】C++入门 —— deque(STL)

阅读导航 前言一、deque简介1. 概念2. 特点 二、deque使用1. 基本操作&#xff08;增、删、查、改&#xff09;2. 底层结构 三、deque的缺陷四、 为什么选择deque作为stack和queue的底层默认容器总结温馨提示 前言 文章绑定了VS平台下std::deque的源码&#xff0c;大家可以下载…...

快速网站开发框架/网站关键词排名批量查询

JavaScript中的BOM对象 浏览器对象模型–Browser ObjectModel (BOM) 一、Window 对象 1、 属性 &#xff08;1&#xff09;有三种方法能够确定浏览器窗口的尺寸&#xff08;浏览器的视口&#xff0c;不包括工具栏和滚动条&#xff09;。 对于Internet Explorer、Chrome、Fi…...

树莓派运行wordpress/国产长尾关键词拘挖掘

先说一下栈和堆栈&#xff0c;我们听老一辈的程序员一般都会说堆栈&#xff0c;其实栈就是堆栈的意思&#xff0c;连着叫只是由于历史的原因。博主04年学数据结构的时候&#xff0c;书上都是说的堆栈&#xff0c;FILO(先进后出)&#xff0c;也经常拿堆栈和队列&#xff0c;FIFO…...

扶贫工作网站怎么做/软件开发交易平台

最近经常会有人问起Citrix UPM如何设定&#xff0c;写了一个入门的手册&#xff0c;欢迎拍砖。 PoC手册 - Lab 13 User Profile Management 设定参考 1.0 https://citrix.sharefile.com/d-sdb2f307914842b38 本文转自sesame.qian 51CTO博客&#xff0c;原文链接&#xff1a;h…...

建设公司建站系统/seo搜索引擎优化薪资水平

SAP锁机制一、SAP为什么要设置锁&#xff1a; 1&#xff0c;保持数据的一致性 如果几个用户要访问同样的资源&#xff0c;需要找到一种同步访问的方法去保持数据的一致性。比如说&#xff0c;在航班预订系 统中&#xff0c;需要检查还有没有空座位&#xff0c;当检查的时…...

电子商务网站建设人才调研/郑州网站seo公司

一、常用加密情况有三种 &#xff1a; 1. 资源加密&#xff0c;如图片&#xff0c;音乐&#xff08;防盗版&#xff09; 2. 网络传输过程中的加密&#xff0c;避免被人拦截并修改数据&#xff08;防作弊&#xff09; 3. 游戏数据加密&#xff08;防作弊&#xff09; 二、加密…...

做网站包括图片设计吗/设计网站

等待函数可使线程自愿进入等待状态&#xff0c;直到一个特定的内核对象变为已通知状态为止。 WaitForSingleObject 函数DWORD WaitForSingleObject( HANDLE hObject, DWORD dwMilliseconds ); 第一个参数hObject标识一个能够支持被通知/未通知的内核对象&#xff08;前面列出的…...