Java类型转换背后的奥妙

一、引用数据类型的强制转换

概述:

在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是由于子类拥有比父类更多的属性功能,所以父类转换为子类需要强制。

定理

在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需要强制转换。主要原因为:子类拥有比父类更多的属性、更强的功能,所以父类转换为子类需要强制。

问题一:是不是只要强制转换都可以把父类转换为子类?

答案是否定的,当我们用一个类型的构造器构造出一个对象时,这个对象的类型就已经确定,也就说它的本质是不会再发生变化的。所谓的类型转换也不能改变对象的本质。而把父类转换为子类,相当于对父类的功能做了扩展,而这一点是不可能做到的。因此父类没有办法通过强制类型转换为子类。

问题二:父类不能强制转换为之类?我经常这样写也没报错啊。

Dog dog1 = (Dog) animal;

对,我们是在代码中这样写,题主也经常这样写。那为啥还说父类不能强制转换为子类呢?让我们来仔细分析下:

首先

刚已经说过,Java语言本身的特性已经决定子类可以转换为父类(这也正是多态),从我们直观的角度来说也好理解,子类转父类,对功能做缩减,父类没有的东西隐藏掉就好了,显然是可以的。

接着

我们再来看下当我们写“Dog dog1 = (Dog) animal;”这种代码的时候,animal就一定是Animal类的实例对象吗?它可以是Animal类及其子类、孙子类任何一个类的实例对象,在编译上都是允许的。

结论

当我们写"Dog dog1 = (Dog) animal;"时,在实际的运行过程中animal其实就是Dog类及其Dog类子类的实例对象,而不是Animal类的实例对象。也就是我们在编码过程中运用多态特性写出各种强制类型转换代码的时候,其实际执行过程中父类的这个实例都只能是子类本身的实例或子类的子类的实例,而不能是父类的实例。而当执行过程中发现类型不一致时就会引发ClassCastException异常

总结一句话:所谓的强制类型转换最终也只是自己对自己的转换,本质上不能做到把父类转换为子类。当我们写代码把父类强制类型转换为子类的时候,实际上这个父类在运行过程本质上要是子类,才能强制类型转换成功。

综述

在Java中我们可以通过继承、向上转型的关系使用父类类型来引用它,这个时候我们是使用功能较弱的类型引用功能较强的对象,这是可行的。但是将功能较弱的类型强制转功能较强的对象时,就不一定可以行了。只有当父类对象的本质是子类才能强制类型转换成功。所谓的强制类型转换也只是自己转换为自己。

看图说明

继承关系

父类转子类失败的情况

父类转子类成功的情况

 

 

 

二、基本数据类型的自动拆包

先看一段代码,结果是啥?

如果你已经快速的得出答案为“fase",那么恭喜你,接下来的内容是值得你停留下来观看的。

如果你认答案为“true",那么兄台,加油!前路漫漫。

先说结论,这段代码将会引发空指针异常。是的你没听错,就是空指针异常。

首先:

我们先看下Integer包装类型的源码,其本质是对int类型的包装。

其次:

我们知道Java中八种基本类型和包装类型是自动拆解包的。

猜想空异常产生的原因:

当作为基本类型的a与包装类型的b进行比较操作的时候发生了拆包操作,而所谓的拆包就是对方法 intValue()的调用去获取包装类真正的value这个值。而由于我们定义的包装类b为null,因此在拆包调用intValue()方法时引发了空指针异常。

验证该猜想也比较简单只需要在Integer的intValue()方法上打上断点,观察执行过程即可。

结论

当基本类型与包装类型进行比较操作的时候,包装类型自动拆包,当包装类型为空时便引发了空异常。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
九宫格问题是蓝桥杯中经典的编程题目之一,其奥妙在于如何通过编程算法来填充九宫格使得每行、每列以及对角线上的数字之和都相等。以下是一种解法: 首先,我们可以使用一个二维数组来表示九宫格,初始化为全0。然后,我们可以选定一个数字作为起始数字,将其放置在九宫格的中间位置(第二行、第二列)。接下来,我们按照如下的规则来填充九宫格: 1. 将当前数字放置在当前位置。 2. 如果当前位置已经到达右上角(第一行最后一列),则将下一个数字放置在左下角(最后一行第一列),即行号加1,列号减1。 3. 如果当前位置的行号超过了最后一行,则将下一个数字放置在当前位置的下方相同列的位置。 4. 如果当前位置的列号超过了最后一列,则将下一个数字放置在当前位置的右方相同行的位置。 5. 如果当前位置已经被占据,则将下一个数字放置在当前位置的下方相同列的位置。 通过按照以上规则不断填充数字,直到九宫格被填满为止。最后,我们可以输出九宫格的结果。 以下是一个示例代码: ```python def fillMagicSquare(n): # 创建一个n x n的二维数组并初始化为全0 magic_square = [[0 for _ in range(n)] for _ in range(n)] # 选定起始数字,并将其放置在九宫格的中间位置 num = 1 i = n // 2 j = n - 1 while num <= n ** 2: if i == -1 and j == n: i = 0 j = n - 2 else: if j == n: j = 0 if i < 0: i = n - 1 if magic_square[int(i)][int(j)]: # 检查当前位置是否已被占据 i = i + 1 j = j - 2 continue else: magic_square[int(i)][int(j)] = num num = num + 1 i = i - 1 j = j + 1 return magic_square # 测试代码 n = 3 magic_square = fillMagicSquare(n) for i in range(n): for j in range(n): print(magic_square[i][j], end=' ') print() ``` 以上代码可以生成一个3x3的九宫格,其每行、每列以及对角线上的数字之和都为15。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值