接上篇:https://developer.aliyun.com/article/1228290?groupCode=java
二、 三元表达式拆包
三元表达式是Java编码中的一个固定语法格式:“条件表达式?表达式1:表达式2”。三元表达式的逻辑为:“如果条件表达式成立,则执行表达式1,否则执行表达式2”。
1. 问题现象
当条件表达式condition等于false时,直接把Double对象value3赋值给Double对象result,按道理没有任何问题,为什么会抛出空指针异常?
2. 问题分析
通过反编译代码,我们得到语句“Double result=condition?value1*value2:value3;”的字节码指令如下:
在第33行,加载Double对象value3到操作数栈中;在第35行,调用Double对象value3的doubleValue方法。这个时候,由于value3是空对象null,调用doubleValue方法必然抛出抛出空指针异常。但是,为什么要把空对象value3转化为基础数据类型double呢?
查阅相关资料,得到三元表达式的类型转化规则:
• 若两个表达式类型相同,返回值类型为该类型;
• 若两个表达式类型不同,但类型不可转换,返回值类型为Object类型;
• 若两个表达式类型不同,但类型可以转化,先把包装数据类型转化为基本数据类型,然后按照基本数据类型的转换规则(byte
根据规则分析,表达式1(value1 * value2)的类型为基础数据类型double,表达式2(value3)的类型为包装数据类型Double,根据三元表达式的类型转化规则判断,最终的表达式类型为基础数据类型double。所以,当条件表达式condition为false时,需要把空Double对象value3转化为基础数据类型double,于是就调用了value3的doubleValue方法进行拆包,当然会抛出空指针异常。
3. 避坑方法
1) 尽量避免使用三元表达式,可以采用if-else语句代替
如果三元表达式中有包装数据类型的算术计算,可以考虑利用if-else语句代替。改写代码如下:
2) 尽量使用基本数据类型,避免包装数据类型的拆装包
如果在三元表达式中有算术计算,尽量使用基本数据类型,避免包装数据类型的拆装包。改写代码如下:
接下篇:https://developer.aliyun.com/article/1228288?spm=a2c6h.13148508.setting.21.7be64f0ebemzoR