JAVA - 关于三元运算符自动拆箱导致NPE的探索

❤️ 三元运算符会有可能导致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看不太懂。以下是运行结果。
JDK8.png

虽然看不懂,但是爱思考的我❤️ ? 想着别人都做过测试,那么他们的测试肯定是真实的,那么出现不一致的情况多半是jdk版本的问题。(没有产生NPE的情况我是采用的JDK8)
然后我就试了一下JDK11发现,在JDK11的情况下会发生NPE,,在这之后又相继试了JDK9,JDK7。发现都会出现NPE。那么也就证明JDK8版本下才会出现这个问题。
以下是JDK7下面的运行情况。
JDK8.png
对比了这两个反编译后的指令,发现jdk7反编译后多了一条指令(上图红框中)。关于这条指令的作用有兴趣的可以自己查一下。
本着,要简单,直观的弄清事情的本质的原则,我又用jad反编译了jdk8和jdk7生成的反编译文件
反编译的jdk7图示:
jdk8版本反编译查看.png
从反编译的文件中可以看出来,在JDK7中,三元运算符的确在第二、第三位操作数分别是基本类型和对象的时候发生了自动拆箱。而“test”因为没有在map中,导致
(Boolean)hashmap.get("test"))为空,从而(Boolean)hashmap.get("test")).booleanValue()发生空指针异常。?
那么这段程序在JDK8下面又是发生了什么呢?同样我又对jdk8下的class文件反编译,得到的结果如图示:
JDK8版本反编译并查看.png
从反编译后的代码中可以看出,在jdk8的情况下,三元运算符并没有对这种情况进行自动拆箱,相反,而是进行了自动装箱。所以这就是为什么在jdk8版本下该代码能够顺利的编译并执行,而其他版本却报NPE的原因了吧。

那么,为什么JDK8要这样处理呢?为什么又要在之后的版本改回去呢?这之中涉及到了什么东西??我也不知道呀。。。如果你有撒好的观点,可以告知我让我也打开下另外的大门!!

# JAVA 

标题:JAVA - 关于三元运算符自动拆箱导致NPE的探索
作者:amore
地址:HTTPS://iamwaiting.cn/articles/2019/10/24/1571853320002.html
彧言:  正在加载今日诗词....

评论

取消