41从零开始学Java之向上转型与向下转型是怎么回事?

news2025/1/18 7:02:36

作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦

千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者

前言

面向对象的第三个特征是多态,实现多态有三个必要条件:继承、方法重写和向上转型。但是我们现在还不知道什么是向上转型,所以在学习多态之前,我们还要先学习Java的类型转换。本篇文章,壹哥就来带大家认识什么是类型转换,看看类型转换都有哪几种情况,以及如何避免类型转换时出现异常。

------------------------------------------------前戏已做完,精彩即开始----------------------------------------------

全文大约【2600】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

配套开源项目资料

Github:

GitHub - SunLtd/LearnJava

Gitee:

一一哥/从零开始学Java

一. 类型转型

将一个类型转换成另一个类型的过程被称为类型转换。我们所说的对象类型转换,一般是指两个存在继承关系的对象,而不是任意类型的对象。如果两个类型之间没有继承关系,就不允许进行类型转换,否则会抛出强制类型转换异常(java.lang.ClassCastException)。
Java语言允许某个类型的引用变量引用子类的实例,而且可以对这个引用变量进行类型转换。Java中引用类型之间的类型转换(前提是两个类是直接或间接的父子关系)主要有两种,分别是向上转型(upcasting)和向下转型(downcasting)

我们先来看下面这张图:

猫、狗、牛、羊都是动物,所以”动物“是父类,猫狗牛羊是具体的子类。我们可以说猫是动物,狗是动物,牛是动物,羊是动物,这个结论肯定没错!但如果我们说,动物是猫,动物是狗,动物是牛,动物是羊,这个结论一定正确吗?那可就不一定了。子类肯定符合父类类型,但反之,父类不一定符合子类类型

接下来壹哥分别对向上转型和向下转型进行讲解。

二. 向上转型

1. 概念

所谓的向上转型,就是父类引用指向子类的对象,也就是把子类对象直接赋给父类引用变量,此时不用强制转换。比如我们说猫是动物,狗是动物,牛是动物,羊是动物,这就是把子类当成父类来用。父类是子类的上级,我们直接把子类向上提拔转型了。

2. 特点

向上转型具有如下特点:

  • 编译类型取决于=号左边,运行类型取决于=号右边;
  • 子类可以调用父类的所有成员,但需遵守访问权限;
  • 父类不能调用子类的特有成员;
  • 最终的运行效果取决于子类的具体实现。

3. 语法

向上转型的基本语法如下所示:

//左侧是父类引用变量,右侧是创建的子类对象,我们可以把它当作父类使用
父类类型 引用名 = new 子类类型();

4. 案例

接下来我们通过一个案例来演示向上转型该如何实现。

/**
 * @author 一一哥Sun 
 * 千锋教育
 * 定义父类---向上与向下转型
 */
public interface Animal {
	//叫
	public void speak();
}

//Dog类实现Animal接口
public class Dog implements Animal {
	@Override
	public void speak() {
		System.out.println("狗子:汪汪");
	}
}

//Cat类实现Animal接口
public class Cat implements Animal {
	@Override
	public void speak() {
		System.out.println("猫子:喵喵");
	}
}

//定义一个测试类
public class AnimalTest {
	public static void main(String[] args) {
		//向上转型
		//父类引用dog变量,指向子类对象new Dog();
        //动物 = 狗;以下代码的意思就是”狗是动物“
		Animal dog=new Dog();
        //向上转型后,可以使用父类Animal中的属性和方法。
		dog.speak();

		//Animal animal=new Cat();效果等同于如下两行代码:
		Cat cat=new Cat();
		Animal animal=cat;
		animal.speak();
	}
}

我们在进行向上转型时,可以写成Animal animal=new Cat(); Animal animal=cat;的形式。就是先创建出cat对象,然后再将cat对象赋值给Animal类型的变量,这样就实现了向上转型。因为Animal是父级类型,Cat是子级类型,Cat是Animal的子类,所以可以直接将cat变量赋值给animal,这就是向上转型。但这种写法比较繁琐,我们通常是直接采用Animal cat=new Cat();的形式,简洁明了。

我们之所以可以实现向上转型,主要是因为两个类型之间是父子关系。比如在本例中,向上转型就等于说”猫是动物,狗是动物“,因为猫狗都是动物的子类,所以这个结论是确定无误的。

三. 向下转型

1. 概念

向下转型则反之,也就是一个已经向上转型的子类对象指向父类引用向下转型后,可以调用子类类型中所有的成员。向下转型时,必须进行强制类型转换。因为父类拥有的成员,子类肯定会有,但子类拥有的成员,父类不一定有。

但要注意,如果父类的引用对象指向的是子类对象,则向下转型时是安全的,即编译时不会出现错误。但如果父类的引用对象是父类本身,那么在向下转型的过程中是不安全的,虽然编译时不会出错,但在运行过程中会出现强制类型转换异常。我们可以使用instanceof运算符来避免出现强制类型转换异常。

2. 特点

向下转型具有如下特点:

  • 只能强制转换父类的引用,不能强制转换父类的对象;
  • 父类的引用必须指向子类目标类型的对象;
  • 向下转型后,父类可以调用子类类型中的所有成员。

3. 语法

向下转型的基本语法如下所示:

//向下转型使用强制类型转换的格式,将父类引用类型转换为子类引用类型
子类类型 引用名 = (子类类型) 父类引用;

4. 案例

接下来我们在上面的案例基础之上,对代码进行改造,在Cat类中增加一个新的方法。

public class Cat implements Animal {
	@Override
	public void speak() {
		System.out.println("猫子:喵喵");
	}

	//给其他动物打招呼
	public void helloAnimal(Animal animal) {
		//向下转型,将父类型转为子类型。
		//此时有可能会出现ClassCastException类型转换异常,因为子类一定属于父类的一员,但父类不一定属于子类。
		//我们说“猫是动物”一定没问题,但如果说“动物是猫”,这个结论未必正确。所以把“动物强转成猫”的过程中,有可能会出现异常。
		//只有两者之间具有明确的父子关系时才能进行强转,否则就会出现类型转换异常。
		
		//向下转型时需要进行类型强转
		Cat cat=(Cat) animal;
        //向下转型后,可以使用子类Cat中的属性和方法。
		cat.speak();
	}
}

//测试类
public class AnimalTest {
	public static void main(String[] args) {
		Animal animal=new Cat();
		animal.speak();
		
		Cat cat=new Cat();
        //这里我们传参时,既可以传递animal,也可以传递cat,但不能传递dog类型,否则会出现java.lang.ClassCastException: 
		//因为class com.yyg.convert.Dog cannot be cast to class com.yyg.convert.Cat。狗不能被转成猫
		//cat2.helloAnimal(dog);
		cat.helloAnimal(animal);

        //Dog dog = new Dog();
		//这里就会编译出错,不允许把Dog对象类型转换成Cat对象类型
		//Cat cat = (Cat)dog;    
	}
}

向下转型就是将父类型转为子类型,但要注意,此时有可能会出现ClassCastException类型转换异常,因为子类一定属于父类的一员,但父类不一定属于子类。我们说“猫是动物”一定没问题,但如果说“动物是猫”,这个结论未必正确。所以把“动物强转成猫”的过程中,有可能会出现异常。只有两者之间具有明确的父子关系时才能进行强转,否则就会出现类型转换异常。

就比如上面的案例中,我们传参时,既可以传递animal,也可以传递cat,但不能传递dog类型,否则会出现java.lang.ClassCastException,因为class com.yyg.convert.Dog cannot be cast to class com.yyg.convert.Cat,狗类不能被转成猫类。

-------------------------------------------------正片已结束,来根事后烟-----------------------------------------------

四. 结语

至此,壹哥就把类型转换给大家介绍完了,我们来看看类型转换的要点吧::

  • 向上转型是父类引用指向子类的对象,不必强制类型转换
  • 向下转型是子类对象指向父类引用,必须进行强制类型转换;
  • 可以强制向下转型最好借助instanceOf进行类型判断;

在下一篇文章中,壹哥会给大家讲解instanceOf关键字的详细用法,敬请关注哦。另外如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。

五. 今日作业

1. 第一题

设计一个父类Person和子类Student、Teacher,实验将Person与Student和Teacher进行类型转换。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL】一文搞懂 MySQL 中的事务

文章目录 0. 前提概要1. 什么是事务?2. 事务的四大特性3. 并发存在的问题4. SQL 标准定义的事务隔离级别5. SpringBoot 解决事务5.1 编程式事务5.2 声明式事务 0. 前提概要 谈事务,一般就是说数据库事务。本篇文章以 MySQL 为例谈一谈事务。 MySQL 的 …

超大规模数据库集群保稳系列之三:美团数据库容灾体系建设实践

本文整理自美团技术沙龙第75期的主题分享《美团数据库攻防演练建设实践》,系超大规模数据库集群保稳系列(内含4个议题的PPT及视频)的第3篇文章。 本文重点介绍了美团数据库的容灾体系建设实践,主要内容包括业务架构、数据库容灾平…

ICASSP 2023 | 解密实时通话中基于 AI 的一些语音增强技术

‍ 动手点关注 干货不迷路 背景介绍 实时音视频通信 RTC 在成为人们生活和工作中不可或缺的基础设施后,其中所涉及的各类技术也在不断演进以应对处理复杂多场景问题,比如音频场景中,如何在多设备、多人、多噪音场景下,为用户提供听…

【ElementUI 表单校验】一个 el-form-item 下多个表单校验(循环校验)

前端项目开发中,表单的应用是必不可少的,不管使用的原生、还是框架如:ElementUI、Ant Design Vue 等。基本的表单应用比较简单,按照文档中的描述使用即可。 官网地址 如下图: 使用 ElementUI 中的表单代码如下&…

国产数据库|GBase 8s 安装卸载与简单使用

作者 | JiekeXu 来源 |公众号 JiekeXu DBA之路(ID: JiekeXu_IT) 如需转载请联系授权 | (个人微信 ID:JiekeXu_DBA) 大家好,我是 JiekeXu,很高兴又和大家见面了,今天和大家一起来看看国产数据库|GBase 8s 安装卸载与简单使用&#…

POSTGRESQL SERVERLESS 是POSTGRESQL 数据库的未来 (译)

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共…

Web3能拯救失落的互联网人吗?

随着互联网的发展,人们逐渐感受到了中心化互联网的局限性和不足之处。 Web3 技术作为一种去中心化的互联网形态,为用户提供了更安全、透明和个人主权的在线体验。本文将探讨 Web3 是否能拯救那些在中心化互联网中感到失落的人们,让我们一起探…

LVS负载均衡——DR模式

一、LVS-DR模式 LVS-DR(Linux Virtual Server Director Server)工作模式,是生产环境中最常用的一 种工作模式。 LVS-DR 模式,Director Server 作为群集的访问入口,不作为网关使用节点 Director Server 与 Real Serve…

软考A计划-电子商务设计师-模拟试题卷二

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

【报告】当“无线通信”遇到“图神经网络”——简单理解

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 课程报告,随便做的,仅供参考~ B站视频:https://www.bilibili.com/video/BV1tM4y1v7t4/ 以下格式默认为:先放图,再放文字 前面的同学介绍了传统方法和经典…

$1$驱动开发

目录 1.驱动大纲: 2.单片机开发属于嵌入式开发吗? 3.RAM裸机代码和驱动有什么区别? 4.Linux系统的组成 5.宏内核、微内核 6.驱动移植 1.驱动大纲: (1)内核模块 (2)字符设备驱…

ArchGuard Co-mate:一次关于大语言模型与架构治理、架构设计的探索

在过去的几个月里,为了探索了 LLM 结合 SDLC、BizDevOps 的可能性,我们(Thoughtworks 开源社区)创建了 ClickPrompt、 AutoDev、DevTi 等一系列的开源项目。从个人的经验来看,未来越来越多的应用将围绕于 LLMCore 设计…

400万总奖金!打一场大厂算法赛事

Datawhale赛事 主办:科大讯飞,伙伴:Datawhale 5月6日,伴随科大讯飞星火认知大模型的发布,2023年度 iFLYTEK A.I. 开发者大赛也正式开启。本届大赛的总奖金池超400万元,除此外还将进一步开放海量数据与核心…

如何使用ArcGIS制作三维地形图

ArcGIS作为专业的GIS软件,不仅可以制作二维地图,制作三维地图也是不在话下,通常我们使用ArcScene来制作三维地图,这里为大家介绍一下制作三维地图的方法,希望能对你有所帮助。 预处理数据 将准备好的矩形面、矩形线和…

Kibana:使用 Kibana 自带数据进行可视化(一)

在今天的练习中,我们将使用 Kibana 自带的数据来进行一些可视化的展示。希望对刚开始使用 Kibana 的用户有所帮助。 前提条件 如果你还没有安装好自己的 Elastic Stack,你可以参考如下的视频来开启 Elastic Stack 并进行下面的练习。你可以开通阿里云检…

接着首发!2023全国1卷数学压轴题解析

早点关注我,精彩不错过! 压轴题原题如下: 以下是压轴题速解,上次突出一个细,这次,自己挑战了一把快! 去年偶然得闲,在高考当天晚上陷入了少年的回忆,重做了一把高考数学压…

“站在后天看明天”:华为给金融广厦架起数字栋梁

在中国古建筑中,有个重要概念,叫做“栋梁”。其中“栋”是指房屋的东西向正梁,起到承担房屋荷载的作用;“梁”则是支撑楼板和其他承重结构的南北向竖梁,起到构筑受重面,支撑屋顶飞檐斗拱的作用。 精彩绝伦、…

如何安装和使用 Hugging Face Unity API

Hugging Face Unity API 提供了一个简单易用的接口,允许开发者在自己的 Unity 项目中方便地访问和使用 Hugging Face AI 模型,已集成到 Hugging Face Inference API 中。本文将详细介绍 API 的安装步骤和使用方法。 安装步骤 打开您的 Unity 项目导航至菜…

2核4G服务器阿里云和腾讯云性能测试对比

阿里云轻量应用服务器2核4G4M带宽优惠价297.98元12个月,腾讯云轻量2核4G5M服务器168元一年,628元3年,2核4G轻量应用服务器阿里云和腾讯云怎么选择?哪个性能比较好?阿腾云分享轻量应用服务器2核4G配置阿里云和腾讯云价格…

3A(3000mA)输出电流比例阀控制器

0.5A(500mA)、0.8A(800mA)、1A(1000mA)、1.5A(1500mA)、2A(2000mA)、2.5A(2500mA)、3A(3000mA)、3.2A(3200mA)等电流输出控制比例阀放大器是用于控制液压系统中的比例阀线圈驱动阀芯运动。它主要由阀体、驱动线圈和放大器。 比例阀是控制方向、流量或压力的元件,它的…