学习Java之如何正确地向上转型与向下转型
作者:一一哥Sun 发布时间:2022-10-12 09:58:10
一. 类型转型
将一个类型转换成另一个类型的过程被称为类型转换。 我们所说的对象类型转换,一般是指两个存在继承关系的对象,而不是任意类型的对象。如果两个类型之间没有继承关系,就不允许进行类型转换,否则会抛出强制类型转换异常(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进行类型判断;
来源:https://juejin.cn/post/7216340356950933564


猜你喜欢
- Java语言的垃圾回收1.垃圾回收机制的基本概念问:1.什么是Java垃圾回收?答:在Java语言的生命周期中,Java运行环境提供了一个系
- 前言日常开发中,特别是音视频开发,需要在界面上渲染视频,比如制作一个播放器、或者视频编辑工具、以及视频会议客户端。通常拿到的是像素格式数据,
- 泛型中 T 类型变量 和 ? 通配符 区别定义不同 :T 是类型变量,? 是通配符使用范围不同:? 通配符用作 参数类型、字段类型、局部变量
- 代码入下:import java.io.*; public class Practice { publ
- 由于CPU的计算频率非常高,每秒计算数十亿次,因此可以将CPU的时间从毫秒的维度进行分段,每一小段叫作一个CPU时间片。目前操作系统中主流的
- 我们先来看看公众号发放现金红包的效果:需要调用商户平台的接口,接口发放规则如下:1.发送频率限制——默认1800/min 2.发送个数上限—
- Java中如何输出像1-2-3-4-5 这样的字符抱歉对于这个问题我甚至不能想到一个合适的标题,但是不重要 以下操作基于 jdk 1.8St
- JDK、JRE、JVMJDK包含JRE,而JRE包含JVMJDK(Java Development Kit)是针对Java开发员的产品,是整
- 1.下载AndroidStudioAndroidStudio官网下载地址:http://developer.android.com/intl
- 使用SwingWorker线程模式谨慎地使用并发机制对Swing开发人员来说非常重要。一个好的Swing程序使用并发机制来创建不会失去响应的
- 脚本之家在以前介绍过关于C#创建、部署、调用WebService的教程,有兴趣的可以参阅:.NET C#创建WebService服务简单实例
- 本文实例讲述了Android实现取消GridView中Item选中时默认的背景色。分享给大家供大家参考,具体如下:1. 取消Gr
- 本文介绍了java 读写Parquet格式的数据,分享给大家,具体如下:import java.io.BufferedReader;impo
- 一、Android Color设置1、在xml文件中想设置颜色直接设置background的属性或者其他的color属性。随便设置一个颜色如
- 方法1:使用内部APIs该方法和其他所有内部没有向外正式公布的APIs一样存在它自己的风险。原理是通过获得WindowManager的一个实
- 在C#中,得益于强大的GC机制,使得我们开发程序变得非常简单,很多时候我们只需要管使用,而并不需要关心什么时候释放资源。但是,GC有的时并不
- 我们在上网的过程中经常看到各种图片,那你知道它是如何实现的吗?接下来就让我们一块探讨一下。 网络图片的浏览可以分为俩部分,基本的页面布局与界
- using System;using System.Data;using System.Data.OleDb;namespace ZFSof
- 目录图像修复API操作效果源码图像修复实际应用中,图像常常容易受损,如存在污渍的镜头、旧照片的划痕、人为的涂画(比如马赛克),亦或是图像本身
- Android透明状态栏只有在4.4之后有。在代码中加入下面几行代码即可实现来源:http://www.cnblogs.com/wangxi