知识屋:更实用的电脑技术知识网站
所在位置:首页 > 教育

Java中的类型转换,表面很简单,实则博大精、深包罗万象

发表时间:2022-03-25来源:网络


细节决定成败!玩Java的您在代码中肯定经常用到类型的转换,但Java中类型转换的一些细节如果您没有研究过的话,未必能说的清楚!

本文旨在以浅显易懂的例子向您讲述一下Java中类型转换的细节!

入题

目前Java中的数据类型有两种,它们分别是primitive(原生类型)和references(引用类型)。尽管这两种数据类型在进行类型转换时看起来很容易,但二者却有着本质的区别。这里先放一张图,大家应该能体现出其中的含义:

没错!primitive类型只是一个值而已,如果你将浮点数1.1转换成了整数1,那你就永远“失去”了1.1,因为就这个例子而言,这种类型的转换是单向的,究其根本原因,还是那句话,primitive类型只是一个值而已。

而具有继承关系的引用类型则不会出现这种情况,因为引用只是指向了堆中的某个对象,而不是像primitive那样包含了那个“对象”,所以引用类型的转换,不会触碰到堆中的实际对象,而只是让这个引用类型多几个方法和属性(向下转换=拓展)或减少几个方法和属性(向上转换=压缩)。

大家可以将引用类型想像成堆中实际对象的远程控制器,具体这个控制器上有几个按钮,取决于它当前所远程控制的对象,如果控制的对象是一架飞机,那这个控制器上应该有个起飞按钮,如果控制的对象是一辆跑车,那这个控制器上应该有个氮气加速按钮。所以引用类型在进行转换时,其实是在拓展或压缩这个远程控制器上的按钮数量与功能的一个过程。

向上转换

从子类引用类型向基类引用类型转换的过程别发信息”向上转换“,所以向上转换跟继承有着密切的关系。通过来讲,向上转换是由java编译器隐式执行的,不用我们程序员操心,这里一定要注意一点,无论是向上转换还是向下转换,都是对象的引用的转换,而不是实际对象的转换,因为对象的实体在堆中没有任何变化。

拿一段代码,看个例子:

如上图所示,“猫咪”类是“动物”类的子类,当创建了一个“猫咪”类的实体之后,可以将这个实体直接赋值“动物”的引用类型,这是隐式向上转换。当然也可以显式的向上转换,但我估计没有程序员会这么做。

这里需要注意的是,在上面的代码中,虽然mm依旧是“猫咪”这种类型,但在隐式向上转换之后,是不能调用“喵喵叫”这个方法的,因为引用变更animal是“动物”这种类型的遥控器,而这个遥控器上只有“吃饭”这个方法,没有“喵喵叫”这个方法,如果确实想调用“喵喵叫”这个方法,那只能进行显式的向下类型转换,这个稍后再谈。

提示:刚才已说过,无论是向上类型转换还是向下类型转换,引用类型所指定的对象必须位于同一继承树上,位于同一继承树上可以是类之间的继承关系,也可以是接口之间的继承关系,也可以是类与接口的实现类型。

向上转换小结:

基类的引用类型可以指向基类对象或所有子类的对象

向上类型转换是由编译器隐式执行的

向下转换

向下类型转换就是基类的引用类型向子类的引用类型转换的过程。还是拿刚才的例子看一下:

向下类型转换会涉及到“白马非马”的问题,因为在Java中,白马就是马,而马却不一定是白马,所以在进行向下类型转换之前,需要先确定这匹马就是白马的情况下,才能将马向下转换成白马。这里应该怎么进行这种确定呢?两种方法:

方法一:使用instanceof运行符

方法二:使用cast()方法

如果不使用这两种方法中的一个事先进行这种检测的话,一旦出现你要将树向下转换成鸟的话,就会抛出运行时异常ClassCastException。

这里建议使用方法二,因为使用方法毕竟比使用运算符来的灵活,功能也更加强大,比如你可以使用泛型构造出一个通用的向下类型转换的工具类。

向下转换小结:

如果想使用子类的属性或方法就需要用到向下类型转换

向下类型转换是显式的使用 ((子类)基类引用)这种运行符

向下类型转换需要事先明确引用的对象确实是某子类的类型,方法有两种,否则会抛出ClassCastException异常

向上转换与多态

这里为什么要提到多态呢?咱们把上面例子的代码微调一下:

基类“动物”定义并实现了“吃饭”这个方法,它表示“吃啥都行”,而子类“猫咪”重写了“吃饭”这个方法,它表示“只吃猫粮”。此时如果编译器执行了隐式的向上转换,即类型为“动物”的引用指向的是类型为“猫咪”的实体,在调用“吃饭”这个方法时,到底是“吃啥都行”还是“只吃猫粮”?

稍微了解java的都知道,答案是“只吃猫粮”,因为这里发生了“多态”!

多态存在的必要条件是:

继承

基类方法的重写

基类引用指向子类对象

所以只要发生了向上转换类型,那在调用基类的某方法时,极有可能会发生多态现象。

总结

到这里应该清楚了吧,别看类型转换只是一堂小小的课程,但其内部却包罗万象:

primitive跟reference的转换完全是两回事

隐式的向上转换极有可能出现多态现象

显式的向下转换可能会抛出异常,有两种方法进行转换前的检测

最重要的一点,引用只是个遥控器,引用的类型转换不会改变其指向的实体对象的任何东西,哪怕是一丁点东西!


收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜