在使用Java的多态机制时,常常使用的一个特性便是子类和父类之间的对象转换。从子类向父类的转换称为向上转换(upcasting),通过向上转换,我们能够在编写程序时采用通用程序设计的思想,在需要使用子类对象的时候,通过把变量定义为父类型,我们可以通过一个变量,使用该父类型的所有子类型实例;从父类型向子类型的转换称为向下转换(downcasting),通过向下转换,我们能在必要的时候,将父类型变量转换成子类型变量,使用一些通过子类型才能够使用的方法。以下是我对于对象转换的一些个人理解,如有不对,欢迎指正,虚心向大神们请教。

首先是从子类向父类的向上转换。向上转换比较直观,总是能够将一个子类的实例转换为一个父类的对象,从继承链的角度,这个特性很容易理解:继承是一种“是一种”的关系,从父类派生出的子类,我们都能理解为,子类总是父类的一个实例。比如说,Fruit类派生出了Orange类,Apple类,Orange和Apple都是Fruit;Animal类派生出了Tiger类和Lion类,Tiger和Lion都是Animal。因此,从子类向父类的转换不需要什么限制,只需直接将子类实例赋值给父类变量即可,这也是Java中的多态的实现机制。

//Test.java
public class Test {public static void main(String args[]) {Animal tiger = new Tiger();Animal lion = new Lion();}
}class Animal {String name;Animal() {name = "animal";}Animal(String name) {this.name = name;}
}
class Tiger extends Animal {Tiger() {super("tiger");}
}
class Lion extends Animal {Lion() {super("lion");}
}

然而从父类向子类的向下转换就稍微复杂一些了。在讲述向下转换之前,也许有些刚学java的朋友会有点不解为什么要使用向下转换,使用多态和动态绑定机制通过父类型变量使用子变量不就可以了么(比如我就曾对此感到疑惑)。这就要考虑到,在继承关系中,有一些方法是不适合由父类定义并由子类继承并重写的,有些方法是子类特有的,不应该通过继承得到,且子类可能也会有自己特有的成员变量,那么在使用多态机制的时候,若我们要通过父类型变量使用到这些子类特有的方法和属性的话,就需要将服类型变量转换成对应的子类型变量。一个典型例子便是标准库中的数据类型包装类:Integer类,Double类,Long类等,它们都继承自Number类,且它们都有一个方法叫做compareTo用于比较两个同样的类型。然而这个方法是这些子类通过实现Comparable接口来实现的,在Number类中并没有该方法的实现,因此若要通过Number类型变量来使用compareTo方法,就要先将Number类转换成子类的对象。

从父类向子类的转换就有限制了。首先,父类变量向子类转换必须通过显式强制类型转换,采取和向上转换相同的直接赋值方式是不行的,;并且,当把一个父类型变量实例转换为子类型变量时,必须确保该父类变量是子类的一个实例,从继承链的角度来理解这些原因:子类一定是父类的一个实例,然而父类却不一定是子类的实例;比如说,Fruit未必是Orange,它可能是Apple;Animal也不一定是Tiger,它可能是Lion。用代码来解释一下:

Animal tiger = new Tiger();
Animal lion = new Lion();

在前面向上转换的代码示例当中,main方法中的这两行代码,意思就是父类型变量tiger是子类Tiger的一个实例,lion是Lion的一个实例。
也就是说,如果要把tiger转换为Tiger类型,必须保证tiger本身是Tiger的一个实例,在上例中,如果要把tiger转换成Lion类型,或是把Lion类型转换为Tiger类型,都是行不通的,在运行时,这会抛出一个运行异常ClassCastException,表示类转换异常。因此,在进行父类向子类的转换时,一个好的习惯是通过instanceof运算符来判断父类变量是否是该子类的一个实例:

Tiger t = null;
if(tiger instanceof Tiger)t = (Tiger)tiger;

如果要通过父类调用子类变量的方法,那么要注意要将父类型变量和强制转换用括号括起来:

Number i = new Integer(3);
System.out.println(((Integer)i).compareTo(new Integer(4)));

因为成员访问运算符.的优先级大于类型转换,所以要用括号括起来保证类型转换先于成员访问进行运算。
前面说到用instanceof判断父类是否是子类的一个实例是一个好习惯,如果不养成这个习惯的话很容易出问题,请看下面这段代码:

Animal animal = new Tiger();
Lion lion = (Lion)tiger;

前面说到,这段代码会在运行时抛出ClassCastException异常,然而,这段代码却是能够编译成功的。原因是因为,Java编译器并没有聪明到能够在编译阶段就知道父类型变量是哪一个子类的实例,所以,将animal转换为Lion类型的代码:(Lion)animal是能够编译通过的,即使事实上我们能看到animal是Tiger的一个实例,因为Animal类型确实能转换成Lion类型,所以这条语句是合法的。所以,如果没有使用instanceof防止不同子类型之间的对象转换,而又不能指望编译器检查出这种转换逻辑错误的话,就很容易犯错了。

Java子类与父类之间的对象转换相关推荐

  1. java如何调用父类的实例对象_java子类调用父类的方法中包含子类重写的实例方法...

    java子类调用父类的方法中包含子类重写的实例方法 # 看题目是不是很绕,这个我也不知道怎么才能更简单的表达了 # 先看代码: public class Common { public static ...

  2. Java子类和父类的初始化执行顺序

    有个朋友在CSDN评论区问我,java子类和父类初始化时各个代码块的执行顺序,我本来写好了一大段回复,点击发表回复,结果没有回复成功,我写的评论也不见了...csdn的评论区编辑体验本来就不好,然后还 ...

  3. php 继承 父类使用子类,在PHP中使用 来 实现子类和父类之间的继承 。

    在PHP中使用 来 实现子类和父类之间的继承 . 更多相关问题 在迄今为止的工业社会,相对于其他要素来说,知识是最为重要也是最为稀缺的. 人们要成为现实的旅游者必须具有旅游动机足够的可以自由支配收入和 ...

  4. java子类和父类实例_java中父类与子类之间的转换示例

    java中父类与子类之间的转换示例有以下三点: 示例一 父类强制转子类 pre class="brush:php;toolbar:false">Father f = new ...

  5. java 子类 父类 转换_Java子类与父类之间的类型转换

    1.向上转换 父类的引用变量指向子类变量时,子类对象向父类对象向上转换.从子类向父类的转换不需要什么限制,只需直接蒋子类实例赋值给父类变量即可,这也是Java中多态的实现机制. 2.向下转换 在父类变 ...

  6. java父类和子类_深入理解子类和父类之间关系

    Java学习的第二篇总结!--子类和父类 深入分析,希望大家多多支持! 从内存角度去分析代码,可以从本质上理解一门语言! 子类从父类继承分成两种: 1.方法的继承: 方法的继承,父类直接把自己的方法转 ...

  7. java子类继承父类实际_java子类继承父类,是否生成父类对象?

    从根本上来说,对象就是一个特殊结构的内存以及可以访问这块内存的代码.所以你这个问题其实就是一个到底如何看什么是对象的. 我不了解现在jvm的具体实现,所以只能就理论上进行下分析. 由于现代的编译器都可 ...

  8. java 子类重写父类的方法应注意的问题

    若想实现一个合格重写方法,而不是重载,那么必须同时满足下面的要求! A.重写规则之一:     重写方法不能比被重写方法限制有更严格的访问级别. (但是可以更广泛,比如父类方法是包访问权限,子类的重写 ...

  9. JAVA子类调用父类构造方法

    子类调用父类的构造方法 父类的构造方法不能被子类继承.以下语句中MyException类继承了java.lang.Exception类. public class MyException extend ...

最新文章

  1. iOS关于自定义rightBarButtonItem
  2. 使用Memcached实现Session共享
  3. python【蓝桥杯vip练习题库】ADV-100第二大整数
  4. [YTU]_2018 ( 约瑟夫问题)
  5. java图书馆管理系统_六天写出来的基于Swing的图书管理系统你不来吐槽一下?
  6. 虚拟主机和托盘服务器,虚拟主机和托盘服务器
  7. HDU - 1151 Air Raid(最小路径覆盖-二分图最大匹配)
  8. 音视频技术开发周刊 | 191
  9. 多线程并发神器--ThreadLocal
  10. Linux使用sendmail发送邮件
  11. 基于REM的移动端响应式适配方案
  12. Linux shell__文件操作
  13. python匹配字符串以结尾_Python-字符串开头或结尾匹配
  14. springboot实现条形码_OkapiBarcode生成条形码
  15. 配置ip地址常用命令及解释
  16. 【问题】eletron引入flash显示“无法加载插件”
  17. 程序设计 :题解+总结
  18. LOG4cxx安装指南
  19. Android移动拼图小游戏
  20. Windows搭建web站点:免费内网穿透发布至公网 1-2

热门文章

  1. 有趣实用的app分享,强烈推荐
  2. 【笔记】 C++中 方向键的输入
  3. python 文本文件中去重复
  4. 斗罗大陆服务器维护,《斗罗大陆武魂觉醒》5月20日停服维护公告
  5. 数据结构与算法--哈夫曼树应用
  6. 2020-10-1 //严蔚敏《数据结构》 //赫夫曼树及其应用:创建顺序赫夫曼树创建及得到赫夫曼编码
  7. dedecms模板配置大概流程
  8. AVS, 主动突围还是坐等救援?
  9. Python文件IO处理技巧: 读写、重定向、间隔符、路径、存在性与文件列表
  10. 2654 最小距离最大