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

本贴最后更新于 1643 天前,其中的信息可能已经时异事殊

❤️ 三元运算符会有可能导致 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 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    180 引用 • 447 回帖
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 291 关注
  • sts
    2 引用 • 2 回帖 • 148 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    915 引用 • 931 回帖 • 1 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1083 引用 • 3461 回帖 • 286 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    7 引用 • 26 回帖
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 2 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    76 引用 • 37 回帖
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    76 引用 • 421 回帖
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 35 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 2 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 21 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 513 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 151 关注
  • 笔记

    好记性不如烂笔头。

    303 引用 • 777 回帖 • 1 关注
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 619 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 641 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 247 回帖 • 177 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 14 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖 • 1 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖 • 3 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 607 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    103 引用 • 294 回帖
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 621 关注
  • abitmean

    有点意思就行了

    21 关注