【Java】:向上转型、向下转型和ClassCastException异常

目录

先用一个生动形象的例子来解释向上转型和向下转型

向上转型(Upcasting)

向下转型(Downcasting)

向上转型

概念

例子

发生向上转型的情况

1.子类对象赋值给父类引用

2.方法参数传递

3.返回值

向下转型

概念

注意事项

例子

ClassCastException异常

概念

例子


先用一个生动形象的例子来解释向上转型和向下转型

向上转型(Upcasting)

想象你有一个动物园,里面有各种不同类型的动物,如狮子、大象、长颈鹿等。动物园的管理员为了方便管理,给每种动物都发放了一个“动物身份证”。这个身份证上并没有详细标明是哪种动物,只是简单地标明“动物”。当管理员查看这些身份证时,他并不关心具体是哪种动物,只要知道它们是动物园里的“动物”就足够了。这就是向上转型的概念。

例子
假设你有一个Lion类(狮子类),它是Animal类(动物类)的子类。当你创建一个Lion对象,并将其赋值给一个Animal类型的引用时,就发生了向上转型。

Animal animal = new Lion(); // Lion对象被向上转型为Animal类型

在这个例子中,animal引用变量只知道它引用的是一个“动物”,而不知道具体是哪种动物。你可以通过animal引用调用Animal类中定义的方法,但不能调用Lion类中特有的方法。

向下转型(Downcasting)

现在,假设动物园的管理员需要对某种特定的动物进行特殊照顾,比如给狮子喂食特定的食物。这时,管理员需要从一堆“动物身份证”中找到狮子的身份证,并将其视为“狮子身份证”。这就是向下转型的概念。

例子
继续上面的例子,如果你想通过animal引用调用Lion类中特有的方法(比如roar()方法,表示狮子吼叫),你需要先将animal引用向下转型为Lion类型。

if (animal instanceof Lion) { // 先检查animal引用是否确实指向Lion对象  Lion lion = (Lion) animal; // Animal类型被向下转型为Lion类型  lion.roar(); // 现在可以调用Lion类中特有的方法了  
}

在这个例子中,你首先使用instanceof运算符检查animal引用是否确实指向一个Lion对象。如果是,你就可以安全地进行向下转型,并调用Lion类中特有的方法。


向上转型

概念


向上转型(Upcasting)是 面向对象编程 中的一个概念,特指将一个子类对象赋值给一个父类类型的引用变量。
这是多态性的一种体现,因为子类对象是父类的一个特例。
在Java中,向上转型是安全的,因为子类继承了父类的所有属性和方法(除了私有方法和构造方法)。

例子

假设有一个父类 Fruit 和子类 Apple

class Fruit {  void eat() {  System.out.println("Eating fruit");  }  
}  class Apple extends Fruit {  @Override  void eat() {  System.out.println("Eating an apple");  }  
}

现在,如果我们有一个 Apple 对象,我们可以将它向上转型为 Fruit 类型:

public class Main {  public static void main(String[] args) {  Apple apple = new Apple();  Fruit fruit = apple; // 向上转型  //也可写做:Fruit fruit = new Apple();fruit.eat(); // 输出 "Eating an apple",因为实际调用的是 Apple 类的 eat 方法  }  
}

在这个例子中,Apple 类的实例 apple 被向上转型为 Fruit 类型,并赋值给 fruit 变量。

尽管 fruitFruit 类型,但由于多态性,调用 eat() 方法时实际上会执行 Apple 类中重写的 eat() 方法。

这就是向上转型和多态性的实际应用。


发生向上转型的情况


1.子类对象赋值给父类引用

当子类的实例直接赋值给父类类型的引用时,会发生向上转型。这是最常见的向上转型场景。

Apple apple = new Apple();  
Fruit fruit = apple; // 向上转型
//也可写为:Fruit fruit = new Apple();

2.方法参数传递

当向一个接受父类类型参数的方法传递一个子类对象时,也会发生向上转型。

void processFruit(Fruit fruit) {  // ...  
}  Apple apple = new Apple();  
processFruit(apple); // 在这里,apple被向上转型为Fruit类型

3.返回值

如果一个方法返回一个子类对象,但是方法的返回类型是父类,那么在返回时也会发生向上转型。

Fruit getFruit() {  Apple apple = new Apple();  return apple; // 在这里,apple被向上转型为Fruit类型返回  
}

向下转型

概念


向下转型(Downcasting)是Java中类型转换的一种,它指的是将一个父类对象转换为子类类型的全过程。这个过程是显式的,需要使用强制类型转换操作符来完成。

在Java中,子类拥有父类的所有属性和方法(除了 private 修饰的属性和方法),同事还可以定义自己特有的属性和方法。

因此,当我们需要将一个父类对象当做子类对象来使用的时候,就需要进行向下转型。

注意事项

  • 向下转型的语法格式如下:
子类类型 变量名 = (子类类型) 父类对象;

  •  只能对已经进行过向上转型的对象进行向下转型:

在Java中,我们不能直接将一个父类对象强制转换为子类对象,除非这个父类对象实际上是子类对象的向上转型。也就是说,我们必须先创建一个子类对象,然后将其向上转型为父类对象,最后再进行向下转换。


  • 向下转型时需要进行类型检查:

为了避免在运行时抛出 ClassCastException 异常,我们在进行向下转型之前,通常需要使用 instanceof 运算符来检查父类对象是否可以被转换为子类类型。


  • 注意访问权限:

在向下转型后,我们可以访问子类特有的属性和方法。但是需要注意的是,如果子类中的某些属性或者方法时 private 的,那么即使进行了向下转型,也无法直接访问这些 private 成员。

例子

下面是一个简单的例子来说明向下转型的用法:

class Animal {  void makeSound() {  System.out.println("Animal makes a sound");  }  
}  class Dog extends Animal {  void bark() {  System.out.println("Dog barks");  }  
}  public class Main {  public static void main(String[] args) {  Animal animal = new Dog(); // 向上转型,将Dog对象转型为Animal类型  if (animal instanceof Dog) { // 使用instanceof进行类型检查  Dog dog = (Dog) animal; // 向下转型,将Animal对象转型为Dog类型  dog.bark(); // 调用Dog类特有的方法bark()  } else {  System.out.println("The animal is not a dog.");  }  }  
}

在这个例子中,我们首先创建了一个 Dog 对象,并将其向上转型为Animal 类型。然后,我们使用 Instanceof 运算符检查这个 Animal 对象是否可以被转换为 Dog 类型。如果可以转换,我们就进行向下转型,将 Animal 对象转换为 Dog 类型,并调用 Dog 类特有的方法 bark() 。

ClassCastException异常

概念

ClassCastException是Java中的一个运行时异常,它发生在试图将一个对象强制转换为不是其实际类型的类类型时。换句话说,当你尝试将一个对象转型为它不兼容的类型时,就会抛出此异常。

这个异常通常发生在向下转型时,如果你没有正确地检查对象的实际类型就进行转换,可能会引发ClassCastException。在Java中,向上转型是安全的,因为子类对象是父类类型的一个特例。但是,向下转型则需要显式的类型转换,并且如果不当使用,就可能导致 ClassCastException。

例子

下面是一个会导致 ClassCastException 异常的例子:

class Animal {}  class Dog extends Animal {}  class Cat extends Animal {}  public class Main {  public static void main(String[] args) {  Animal animal = new Cat(); 
// 向上转型,Cat 是Animal的子类,所以这是安全的  Dog dog = (Dog) animal; 
// 尝试向下转型,但是 animal 实际上是 Cat 类型,所以会抛出 ClassCastException  }  
}

在这个例子中,我们创建了一个 Cat 对象,并将其赋值给 Animal 类型的变量 animal。然后,我们尝试将这个 Animal 类型的变量强制转换为 Dog 类型。但是,因为这个 Animal 对象实际上是 Cat 类型的,所以转换会失败,并抛出一个 ClassCastException

为了避免这种异常,你可以在向下转型之前使用 instanceof 操作符来检查对象是否可以被安全地转换为目标类型:

if (animal instanceof Dog) {  Dog dog = (Dog) animal; // 这是安全的,因为已经检查了类型  
} else {  System.out.println("The animal is not a dog.");  
}

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

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

相关文章

Electron学习笔记(一)

文章目录 相关笔记笔记说明 一、轻松入门 1、搭建开发环境2、创建窗口界面3、调试主进程 二、主进程和渲染进程1、进程互访2、渲染进程访问主进程类型3、渲染进程访问主进程自定义内容4、渲染进程向主进程发送消息5、主进程向渲染进程发送消息6、多个窗口的渲染进程接收主进程发…

如何取消格式化SD卡并恢复丢失的数据?

在相机中格式化SD卡后,您将丢失卡上的所有文件。如果有恢复形成操作的选项,您可以轻松取回文件。然而,相机或任何其他设备中没有这样的选项。它无法直接取消格式化相机SD卡,但您仍然可以从格式化的SD卡中恢复文件。 为什么格式化后…

pycharm本地文件更新至虚拟机

tools–>deployment–>configuration root path的路径要跟远程路径对齐,方便后续运行 mapping映射,本地路径和远程路径 点击Browse 可以在右侧同步查看更新情况

Jmeter使用While控制器

1.前言 对于性能测试场景中,需要用”执行某个事物,直到一个条件停止“的概念时,While控制器控制器无疑是首选,但是在编写脚本时,经常会出现推出循环异常,获取参数异常等问题,下面总结两种常用的…

一文详解多模态智能体(LMAs)最新进展(核心组件/分类/评估/应用)

大型多模态智能体 文章链接:https://arxiv.org/pdf/2402.15116 github地址:https://github.com/jun0wanan/awesome-large-multimodal-agents 大语言模型(LLMs)在为基于文本的AI智能体提供动力方面取得了卓越的表现,赋…

微信小程序 17:小程序使用 npm 包和组件应用

目前,小程序中已经支持实用 npm 安装第三方包,从而提高小程序的开发效率,但是在小程序中使用 npm 包有三个限制: 不支持 Node.js内置库的包不支持依赖于浏览器内置对象的包不支持依赖于 C插件的包 Vant Weapp Vant Weapp是有赞…

山东济南最出名的起名大师颜廷利教授:当代中国教育界的泰斗

山东济南最出名的起名大师颜廷利教授:当代中国教育界的泰斗。 四川成都、重庆、香港、台湾、辽宁沈阳、大连、湖南长沙、宁夏第一起名大师的老师颜廷利教授被誉为世界上思想境界最高的人之一。 北京、上海、天津、浙江杭州、江苏南京、宁夏银川最权威起名大师的老师…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《规模化屋顶光伏接入配电网的建设决策》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Scratch四级:第08讲 排序算法

第08讲 排序算法 教练:老马的程序人生 微信:ProgrammingAssistant 博客:https://lsgogroup.blog.csdn.net/ 讲课目录 常考的排序算法项目制作:“三个数排序”项目制作:“成绩查询”项目制作:“排序”项目制…

【机器学习】LoFTR:革命性图像特征批评技术等领跑者

LoFTR:革命性图像特征匹配技术的领跑者 一、引言二、LoFTR技术的创新之处三、LoFTR技术的实现原理四、LoFTR技术的代码实例五、结语 一、引言 在3D计算机视觉领域,图像特征匹配技术一直是研究的热点和难点。随着技术的不断发展,传统的特征检…

语言:C#

一、VSCode生成exe 二、

java sql中 大于 小于 大于等于 小于等于 代替符号

在写java时sql会经常会忘记大于小于号的表示方法导致无法运行&#xff0c;总结一下 第一种方法&#xff1a; < &#xff1a;< < &#xff1a; < &#xff1a;> &#xff1a; > sql如下&#xff1a; create_at > #{startTime} and create_at < #{end…

鸿蒙布局Column/Row/Stack

鸿蒙布局Column/Row/Stack 简介我们以Column为例进行讲解1. Column({space: 10}) 这里的space: 10&#xff0c;表示Column里面每个元素之间的间距为102. width(100%)&#xff0c;height(100%) 表示宽高占比3. backgroundColor(0xffeeeeee) 设置背景颜色4. padding({top: 50}) 设…

《构建智能财务预算与管控技术架构:实现企业财务管理的高效运作》

在当今数字化时代&#xff0c;企业财务预算与管控技术的应用已成为企业管理的关键一环。通过构建智能化的财务预算与管控技术架构&#xff0c;企业能够实现财务管理的精细化、智能化和高效化&#xff0c;从而更好地应对市场竞争和风险挑战&#xff0c;提升企业的竞争力和盈利能…

JAVA多线程并发(一)-- JAVA线程简介

一、JAVA线程实现/创建方式 在Java中&#xff0c;线程的创建与实现主要有三种方式&#xff1a;继承Thread类、实现Runnable接口以及使用Callable接口配合FutureTask和ExecutorService。下面将分别介绍这三种方式&#xff0c;并通过实际案例代码进行演示。 1. 继承Thread类 T…

Oracle如何收缩减小表空间大小

比如我们发现一个表空间占用比较大&#xff0c;但是空闲空间很大&#xff0c;想要减小表空间占用大小。查看表空间的情况 发现BETEST表空间占用大&#xff0c;但是剩余大小比较大&#xff0c;可以减小存储占用。 如果我们想减小到100MB&#xff0c;那么就登录其用户执行&#…

回溯之组合总和II

上一篇文章使用回溯解决了组合总和I&#xff0c;这次使用回溯解决组合总和II&#xff0c;下面先给出回溯的模板代码。 private void backtracking(参数1,参数2,...){if(递归终止条件){收集结果;return;}for(遍历集合){处理;backtracking(参数1,参数2,...); // 递归;回溯;} }组…

进程的共享主存通信实验

进程的共享主存通信 【预备知识】 共享存储区为进程提供了直接通过主存进行通信的有效手段&#xff0c;不像消息缓冲机制那样需要系统提供缓冲&#xff0c;也不像pipe机制那样需要事先建立一个特殊文件&#xff0c;而是由通信双方直接访问某些共享虚拟储存空间。在Linux中&…

2024情感聊天赛道,al工具制做,视频一分钟一条,日入500+

在这个领域&#xff0c;我们可以利用AI技术快速制作情感文章和闲聊内容。基本原理是结合热门创意文案&#xff0c;通过AI生成情感聊天短视频&#xff0c;然后在各大网站进行独家代理&#xff0c;这个领域的竞争相对较小&#xff0c;可以说是一片蓝海。 项 目 地 址 &#xff…

ue5地编模块学习记录

ue5网站功能3d溜溜网下载模型https://anyconv.com/max-to-fbx-converter/3dmax转换fbx模型解决问题记录 一、光源 搜索光源搜索不到的时候可以点击 窗口> 对场景内的光照进行处理