❤️ 三元运算符会有可能导致 NPE
今天我正在摸鱼的时候,老大大大爷 ❤️ 突然给我发消息说今天该我分享知识点呀 😰 😰 ,然后我就想到之前在 HollisChuang's Blog(大佬,建议没事就去逛逛)上看到的一篇文章 《自动拆箱导致空指针异常》(不了解可以先看看这篇文章,知道的请无视。。。),里面讲解了一个关于三元运算符中发生自动拆箱导致 NPE 的知识点,我感觉还比较有意思,于是就分享给群里的小伙伴 👍 👍 。
由于之前看过,没实践过,而今天正好分享了这个知识点,所以我就准备自己试验下。
按照文章中的例子,我敲下了同样的代码:
import java.util.*;
public class Test{
public static void main(String []args){
/*
* 下面两条语句即需要测试的语句
*/
Map<String,Boolean> map = new HashMap<String, Boolean>();
Boolean b = (map!=null ? map.get("test") : false);
}
}
然后编译运行,纳尼,尽然没报错。于是又准备 javap 反编译看一下,emmm 看不太懂。以下是运行结果。
虽然看不懂,但是爱思考的我 ❤️ 👍 想着别人都做过测试,那么他们的测试肯定是真实的,那么出现不一致的情况多半是 jdk 版本的问题。(没有产生 NPE 的情况我是采用的 JDK8)
然后我就试了一下 JDK11 发现,在 JDK11 的情况下会发生 NPE,,在这之后又相继试了 JDK9,JDK7。发现都会出现 NPE。那么也就证明 JDK8 版本下才会出现这个问题。
以下是 JDK7 下面的运行情况。
对比了这两个反编译后的指令,发现 jdk7 反编译后多了一条指令(上图红框中)。关于这条指令的作用有兴趣的可以自己查一下。
本着,要简单,直观的弄清事情的本质的原则,我又用 jad 反编译了 jdk8 和 jdk7 生成的反编译文件
反编译的 jdk7 图示:
从反编译的文件中可以看出来,在 JDK7 中,三元运算符的确在第二、第三位操作数分别是基本类型和对象的时候发生了自动拆箱。而“test”因为没有在 map 中,导致
(Boolean)hashmap.get("test"))
为空,从而 (Boolean)hashmap.get("test")).booleanValue()
发生空指针异常。😰
那么这段程序在 JDK8 下面又是发生了什么呢?同样我又对 jdk8 下的 class 文件反编译,得到的结果如图示:
从反编译后的代码中可以看出,在 jdk8 的情况下,三元运算符并没有对这种情况进行自动拆箱,相反,而是进行了自动装箱。所以这就是为什么在 jdk8 版本下该代码能够顺利的编译并执行,而其他版本却报 NPE 的原因了吧。
那么,为什么 JDK8 要这样处理呢?为什么又要在之后的版本改回去呢?这之中涉及到了什么东西??我也不知道呀。。。如果你有撒好的观点,可以告知我让我也打开下另外的大门!!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于