当熟悉的三元表达式遇到装/拆箱发生了未预料到的NPE 如下代码都是在 jdk 1.8.0_172 版本下运行java
java代码以下,注释位置会抛出NPE:优化
public class TestThree { public static void main(String[] args) { Double a = 1D; Double b = 2D; Double c = null; Double d = false ? a*b : c; // 这里会抛出NPE System.out.println("finished"); } }
猜想因为a*b,Double都进行了拆箱,c由于是null,进行拆箱时就抛出了NPE,为了验证,咱们使用javap -c命令看下简单的字节码信息code
如上图所示,第12--21行即c的操做过程,能够看出第18行Double.doubleValue获取c的小double值就是抛出NPE的罪魁祸首。blog
可是有个疑问,很明显能够看出,通过javac的优化,ab根本不会执行,a、b也都没有拆箱的操做,为何要对c进行拆箱呢,直接将null赋值给d不是更简捷,仅仅由于代码中使用了ab进行乘法运算就致使了c的拆箱吗? 咱们来作个验证:数学
public class TestThree { public static void main(String[] args) { //Double a = 1D; //Double b = 2D; Double c = null; Double d = false ? null : c; // 这里不会抛出NPE System.out.println("finished"); } }
上面的代码可以成功运行,咱们来看下反编译出的字节码内容编译
能够看到确实没有对c的Double.valueOf方法的调用,以前对c的拆箱确实是因为a*b运算致使的。class
至此,咱们能够得出一个猜测,在三元表达式中,若是一个结果执行了数学运算,即便表达式的判断条件短路了此运算,另一个结果也会因为拆箱而可能致使NPE的发生。jdk
最后留一个问题,下面的代码是否会抛出NPE,其反编译后的代码又会是什么样子的,想象一下~方法
public class TestThree { public static void main(String[] args) { Double a = 1D; Double b = 2D; Double c = null; Double d = false ? 1 : c; // 这里会不会抛出NPE??? System.out.println("finished"); } }