(Java)向上转型和向下转型

1.向上转型

1.1 向上转型的概念

向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
举个例子:

//Animal是Cat的父类
Animal animal = new Cat("翠花",2);

animal是父类类型,但可以引用一个子类对象,因为大范围可以囊括小范围,是安全的,就比如小猫和小狗它们在物种上来说都属于动物。

1.2 向上转型的使用

【使用场景】

  • 直接赋值
  • 方法传参
  • 方法返回

以下是我们接下来需要用到的一些类:

//Animal类
public class Animal(){public String name;public int age;public Animal(String name, int age){this.name = name;this.age = age;}public void eat(){System.out.println(name + "吃饭");}
}
//继承Animal的Cat类
public class Cat extends Animal{public Cat(String name, int age){super(name, age);}@Overridepublic void eat(){System.out.println(name + "吃鱼");}
}
//继承Animal的Dog类
public class Dog extends Animal{public Dog(String name, int age){super(name, age);}@Overridepublic void eat(){System.out.println(name + "吃骨头");}
}

每个场景的应用:

public class TestAnimal {// 1. 方法传参:形参为父类型引用,可以接收任意子类的对象public static void eatFood(Animal a){a.eat();}// 2. 作返回值:返回任意子类对象public static Animal buyAnimal(String word){if("狗".equals(word) ){return new Dog("狗狗",1);}else if("猫" .equals(word)){return new Cat("猫猫", 1);}else{return null;}}public static void main(String[] args) {Animal cat = new Cat("小猫",2); // 3. 直接赋值:子类对象赋值给父类对象Dog dog = new Dog("小狗", 1);eatFood(cat);eatFood(dog);Animal animal = buyAnimal("狗");animal.eat();animal = buyAnimal("猫");animal.eat();}
}

1.3 代码详解:

  • 1.方法传参:
public static void eatFood(Animal a){a.eat();
}

这个方法的参数类型是Animal,Animal是Cat和Dog的父类,那这里也可以接收任意子类的对象,就像在main方法中写的这样:

eatFood(cat);//参数是Cat对象
eatFood(dog);//参数是Dog对象
  • 2.方法返回
// 2. 作返回值:返回任意子类对象
public static Animal buyAnimal(String word){if("狗".equals(word) ){return new Dog("狗狗",1);}else if("猫" .equals(word)){return new Cat("猫猫", 1);}else{return null;}
}

这个方法的返回值的类型是Animal,这里我们同样可以返回Animal的子类,故这里我们可以直接返回Cat对象和Dog对象。

  • 3.直接赋值:
Animal cat = new Cat("小猫",2); 

这个就比较直观一点了,我们可以看到子类对象可以直接赋值给父类对象。

向上转型的优点:让代码实现更加简单灵活
向上转型的缺点:不能调用到子类特有的方法

2.向下转型

2.1 向下转型的概念

将一个子类对象经过向上转型之后,就无法调用到子类特有的方法了,但有时候可能需要调用子类特有的方法,那么此时,我们将父类引用再还原为子类对象即可,这就是向下转型。

那么这个时候,我们就需要考虑到一个问题了,上述介绍的向上转型,它的原理是大范围可以囊括小范围,就像小猫和小狗从物种上来说,它们都属于动物,那么现在将两者的位置替换之后,我们提到动物,就一定是小猫或者小狗吗,那可不一定,所以向下转型一般来说是不安全的。

我们先来准备接下来需要用到的一些类,与上面的类有所不同的是,这次里面增加了两个新的 方法,即每个子类中特有的方法.

//Animal类
public class Animal(){public String name;public int age;public Animal(String name, int age){this.name = name;this.age = age;}public void eat(){System.out.println(name + "吃饭");}
}
//继承Animal的Cat类
public class Cat extends Animal{public Cat(String name, int age){super(name, age);}@Overridepublic void eat(){System.out.println(name + "吃鱼");}public void mew(){System.out.println(name + "喵喵叫");}
}
//继承Animal的Dog类
public class Dog extends Animal{public Dog(String name, int age){super(name, age);}@Overridepublic void eat(){System.out.println(name + "吃骨头");}public void bark(){System.out.println(name + "汪汪叫");}
}

2.2 向下转型的应用:

public class TestAnimal {public static void main(String[] args) {Cat cat = new Cat("小猫",2);Dog dog = new Dog("小狗", 1);
// 先向上转型 向上转型后只能调用到父类中的方法Animal animal = cat;animal.eat();animal = dog;animal.eat();//animal.bark(); 编译报错//向下转型cat = (Cat)animal;cat.mew();dog = (Dog)animal;dog.bark();}
}

2.3 代码详解:

animal = dog;
animal.eat();
animal.bark();//编译报错

当我们写出上面第三句代码时,就会出现编译报错,因为编译器在编译时是将animal当成Animal对象处理的,而不是Dog对象,而Animal类中没有bark方法,因此会编译失败,所以我们要想调用Dog类和Cat类中特有的对象,就要这样做:将父类引用强制转换为子类引用

cat = (Cat)animal;
cat.mew();

这么写时,编译不会报错,但运行时会抛出异常,因为animal最后实际指向的是dog,现在要强制还原为猫,无法正常还原,运行时会抛出ClassCastException异常。

dog = (Dog)animal;
dog.bark();

这里animal本来指向的是dog,因此将animal还原为Dog也是安全的。

  • 从上述代码中,我们也可以看出,向下转型并不安全,一旦转换失败,运行时就会抛出异常。Java中为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转换。

2.4 instanceof 的使用:

public class TestAnimal {public static void main(String[] args) {Cat cat = new Cat("小猫",2);Dog dog = new Dog("小狗", 1);//向上转型Animal animal = cat;animal.eat();animal = dog;animal.eat();//向下转型//表达式为false的话就不会执行里面的代码if(animal instanceof Cat){cat = (Cat)animal;cat.mew();}if(animal instanceof Dog){dog = (Dog)animal;dog.bark();}}
}

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

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

相关文章

信息与计算科学:“数学 + 计算机”,奏响未来科技新乐章

在当今科技飞速发展的时代,有一个专业如同一颗闪耀的新星,散发着独特的魅力,那就是信息与计算科学专业。 一、专业全貌:追根溯源,领略交叉之美 (一)专业的诞生与发展 1998 年,教育…

一图解千言,了解常见的流程图类型及其作用

在企业管理、软件研发过程中,经常会需要进行各种业务流程梳理,而流程图就是梳理业务时必要的手段,同时也是梳理的产出。但在不同的情况下适用的流程图又不尽相同。 本文我们就一起来总结一下8 种最常见的流程图类型 数据流程图 数据流程图&…

RHCE——例行性工作

准备工作 [rootlocalhost ~]# cat /etc/yum.repos.d/aliyun.repo [ali-app] nameali-app baseurlhttps://mirrors.aliyun.com/centos-stream/9-stream/AppStream/x86_64/os/ gpgcheck0[ali-base] nameali-base baseurlhttps://mirrors.aliyun.com/centos-stream/9-stream/Base…

JS | JS中类的 prototype 属性和__proto__属性

大多数浏览器的 ES5 实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype属性。Class 作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链。 构造函数的子类有prototype属性。‌ …

倍福中控显示屏维修控制面板CP7732-1207-0030

使用的环境条件不当可能会损坏设备。 保护设备,防止灰尘、湿气和热量进入。 使用注意事项: 空气流通不畅 设备安装不正确会阻碍设备内的空气流通,从而导致过热和功能受损。 只能按所示方向将设备安装在相应的壁上。 该设备设计用于安装在…

05 P1157 组合的输出

题目&#xff1a; 代码&#xff1a; #include<iostream> using namespace std; # define M 500 #include<algorithm>int sa[100005],k,n,count1;bool func(int n) {int mark0;if(n1){return 1;}else{for(int i2;i<n-1;i){if(n%i0){mark1;return 0;}}if(mark0)r…

强化学习案例:美团是如何在推荐系统中落地强化学习

目录 美团的强化学习应用场景和分析 场景举例 使用原因 强化学习的六大要素 智能体 环境 行动 奖励 目标 状态 美团强化学习模型设计 美团强化学习工程落地 总体的数据结构关系图 实现步骤 1. 日志收集与实时处理&#xff08;Log Collector, Online Joiner&…

PyTorch 2.5 发布带来一些新特性和改进

官网&#xff1a;https://github.com/pytorch/pytorchGitHub&#xff1a;https://github.com/pytorch/pytorch原文&#xff1a;https://github.com/pytorch/pytorch/releases/tag/v2.5.0 主要亮点 (Highlights)] SDPA CuDNN 后端&#xff1a;为 torch.nn.functional.scaled_d…

C++标准模板库--vector

vector 介绍 vector&#xff08;向量&#xff09;是一种序列容器&#xff0c;表示为可以改变大小的数组。vector中的元素使用连续的存储位置&#xff0c;这意味着也可以使用指向其元素的常规指针偏移量来访问任意元素&#xff0c;且与数组一样高效。但与数组不同的是&#xff…

React Componet类组件详解(老项目)

React类组件是通过创建class继承React.Component来创建的&#xff0c;是React中用于构建用户界面的重要部分。以下是对React类组件的详细解释&#xff1a; 一、定义与基本结构 类组件使用ES6的class语法定义&#xff0c;并继承自React.Component。它们具有更复杂的功能&#…

流量PID控制(开度前馈量计算+辅助PID)

和流体流速(瞬时流量)相关的计算请参考下面文章链接: 1、PLC通过伯努利方程近似计算水箱流量 PLC通过伯努利方程近似计算水箱流量(FC)-CSDN博客文章浏览阅读1.6k次。本文介绍了如何使用PLC通过伯努利方程近似计算水箱中的液体流量,主要涉及流量计算、模型验证、梯形图编程及…

C++学习路线(二十)

项目 模块划分 推箱子游戏 地图初始化 热键控制 推箱子控制 游戏结束 地图初始化 坐标系&#xff08;650&#xff0c;650&#xff09; 地图表示&#xff1a; 使用二维数组 游戏道具展示&#xff08;墙 箱子 箱子目的地 小人 地板&#xff09; 判断游戏…

java基于SpringBoot+Vue+uniapp微信小程序的自助点餐系统的详细设计和实现(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

【H∞鲁棒控制】状态反馈、输出反馈、混合灵敏度H∞控制器设计

最近在学H∞鲁棒控制&#xff0c;因为后面项目中可能要用到此控制方法&#xff0c;所以提前进行了学习&#xff0c;刚开始接触感觉看不太懂&#xff0c;涉及的数学专业知识较深&#xff0c;而且网上资料也比较零星且局限&#xff0c;摸爬了好几天才搞懂了点&#xff0c;现自己总…

「Java服务」快速接入SkyWalking方法指南

一、背景 背景&#xff1a;Apache SkyWalking 是一个开源的分布式应用性能监控&#xff08;APM&#xff09;系统&#xff0c;主要用于监控微服务、云原生和容器化应用的性能。接入SkyWalking可以排查以智能投放服务为主的服务响应问题 技术架构 SkyWalking 的核心架构包括以…

银河麒麟V10系统+Windows10双系统启动顺序正确修改方法

***正确可行方法***&#xff0c;测试OK且稳定&#xff1b; 银河麒麟桌面操作系统V10是一款适配国产软硬件平台并深入优化和创新的新一代图形化桌面操作系统&#xff0c;同源支持国内外主流处理器架构&#xff0c;并不断使能GPU、桥片、网卡等各种新硬件&#xff0c;提供更优的软…

vue3学习之插槽slot

关于slot web组件内部的占位符&#xff0c;可以使用自己的标记填充这个占位符 &#xff0c;具名插槽就是在slot标签上添加name属性&#xff08;https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/slot&#xff09; vue3官方文档&#xff1a;https://cn.vuejs.org/gui…

深入解析Java 22:专栏介绍

深入解析Java 22&#xff1a;专栏介绍 Java&#xff0c;作为一种广泛使用的编程语言&#xff0c;一直以来都在不断地发展和改进。2024年3月19日&#xff0c;Java 22的GA版本正式发布&#xff0c;带来了众多令人瞩目的新特性和性能优化。本专栏将深入解析Java 22&#xff0c;带…

AD9680(adc直采芯片)使用说明

写这篇文章之前我是没有使用过AD9680的芯片&#xff0c;但是使用过GMS011芯片&#xff08;是国内24S&#xff09;下的公司出来的芯片&#xff0c;寄存器和管脚全对标。 在这里我就大概说一下芯片的说用方法 一、硬件设计 该芯片支持双通道射频直采 支持协议JESD204B 14位 采样…