来源 | 锅外的大佬

在Java语言中,处理空指针往往是一件很头疼的事情,一不小心,说不定就搞出个线上Bug,让你的绩效考核拿到3.25。

最近,新出的Java14,相信大家都有所耳闻,那么今天就来看看,面对NullPointerException,Java14有哪些更好的处理方式呢?

传统的 NullPointerException

我们编码过程中呢,经常会使用链式调用的方式来写代码,这样写起来很方便,也很清晰,但是,一旦出现NullPointerException,那就头大了,因为你很难知道异常是在什么时候开始发生的。

举个简单的例子,就比如下面的代码,要找到公司某个员工的户籍所在地,我们这样来调用

String city = employee.getDetailInfos().getRegistryAddress().getCity();

在链式调用的过程中,如果employee, getDetailInfos(),或者 getRegistryAddress() 为空,JVM就会抛出 NullPointerException。

那么导致异常的根本原因是什么?如果不使用调试器,很难确定哪个变量为空。而且,JVM也只会打印导致异常的方法、文件名和行号,仅此而已。那么下面,我将带大家了解Java 14如何通过 JEP 358 解决这个问题。

增强型 NullPointerException

SAP在2006年为其商业JVM实现了增强型的 NullPointerException。2019年2月,它被提议作为OpenJDK社区的一个增强,之后很快,它成为了一个JEP。所以,该功能在2019年10月完成并在JDK 14版本推出。

本质上,JEP 358 旨在通过描述某个变量是 “null” 来提高 JVM 生成的 “NullPointerException” 的可读性。JEP 358通过在方法、文件名和行号旁边描述为 null 的变量,带来了一个详细的 NullPointerException 消息。它通过分析程序的字节码指令来工作。因此,它能够精确地确定哪个变量或表达式是null。最重要的是,JDK 14中默认关闭详细的异常消息。要启用它,我们需要使用命令行选项:

-XX:+ShowCodeDetailsInExceptionMessages

详细的异常信息

考虑在激活 ShowCodeDetailsInExceptionMessages 标志的情况下再次运行代码:

Exception in thread "main" java.lang.NullPointerException:  Cannot invoke "RegistryAddress.getCity()" because the return value of"com.developlee.java14.helpfulnullpointerexceptions.HelpfulNullPointerException$DetailInfos.getRegistryAddress()" is null  at com.developlee.java14.helpfulnullpointerexceptions.HelpfulNullPointerException.main(HelpfulNullPointerException.java:10)

这一次,从附加信息中,我们知道员工的个人详细信息丢失的注册地址导致了我们的异常。从这个增强中获得的信息可以节省我们调试所用的时间。

JVM由两部分组成详细的异常消息。第一部分表示失败的操作,这是引用为 null 的结果,而第二部分标识了 null 引用的原因:

Cannot invoke "String.toLowerCase()" because the return value of "getEmailAddress()" is null

为了生成异常消息,JEP 358 重构了将空引用推送到操作数堆栈上的部分源代码。

技术方面

现在我们已经很好地理解了如何使用增强的NullPointerExceptions标识 null 引用,让我们来看看它的一些技术方面。

首先,只有当JVM本身抛出一个 NullPointerException 时,才会进行详细的消息计算,如果我们在Java代码中显式抛出异常,则不会执行计算。原因是因为:在这些情况下,很可能已经在异常构造函数中传递了一条有意义的消息。

其次,JEP 358懒汉式地计算消息,这意味着只有当我们打印异常消息时才调用增强的NullPointerException,而不是当异常发生时就调用。因此,对于通常的JVM流程不应该有任何性能影响,在那里我们可以捕获并重新抛出异常,因为咱并不会只想打印异常消息。

最后,详细的异常消息可能包含源代码中的局部变量名。因此,我们可以认为这是一个潜在的安全风险。但是,只有在运行使用激活的 -g 标记编译的代码时,才会发生这种情况,该标记会生成调试信息并将其添加到类文件中。请考虑一个简单的示例,我们已编译该示例以包含以下附加调试信息:

Employee employee = null;employee.getName();

当执行以上代码时,异常信息中会打印本地变量名称:

"com.developlee.java14.helpfulnullpointerexceptions.HelpfulNullPointerException$Employee.getName()"because "employee" is null

相反,在没有额外调试信息的情况下,JVM 只提供它在详细消息中所知道的变量:

Cannot invoke"com.developlee.java14.helpfulnullpointerexceptions.HelpfulNullPointerException$Employee.getName()"because "<local1>" is null

JVM 打印编译器分配的变量索引,而不是本地变量名(employee)。

关于NullPointerException的处理到这里就结束了,通过Java14增强的NullPointerException,我们可以很快速的定位代码问题的原因所在,更快的调试代码,节约时间,提高效率。

已经安装了Java14的朋友可以试试看哦~

往期推荐

Spring Boot 解决跨域问题的 3 种方案

把 14 亿人都拉到一个微信群,在技术上能实现吗?

这样统计代码执行耗时,才足够优雅!

来看看Google的未来工作环境设计,有你喜欢的元素吗?

小小登录,大大讲究!你的登录功能都做到位了吗?

如果你喜欢本文,欢迎关注我,订阅更多精彩内容

关注我回复「加群」,加入Spring技术交流群

Spring For All社区3.0开始测试啦!

学习的路上不孤单,快来注册分享与交流吧!

点击阅读原文直达新版社区

这几天研究了一下JDK14,发现它处理NPE的方式,真香!相关推荐

  1. PNAS新研究:剑桥学者发现,有些 AI 模型无法被计算

    来源:AI科技评论 作者:Ailleurs 编辑:陈彩娴 近日,剑桥学者在<美国科学院院报>(PNAS)上发表了一篇名为"The Difficulty of Computing ...

  2. 从Richard Young教授的系列研究看超级增强子发现背后的故事 (附超级增强子鉴定代码)

    欢迎关注天下博客:http://blog.genesino.com/2018/04/super-enhancer/ Richard Young教授,美国科学院院士,就职于Whitehead研究所,是基 ...

  3. 谁说必须多组学?非靶代谢基础研究思路及biomarker发现之路

    标题:基于LC-MS的血清代谢组学分析在肾癌诊断.分期和生物标志物发现中的应用 Title: LC-MS based serum metabonomic analysis for renal cell ...

  4. 利用人工智能预测乐高包装的LEGO商标尺寸,深入研究竟有惊人发现

    导语:不知道大家会不会有天突发奇想,想知道乐高包装上的经典红底白字LOGO的尺寸,到底是标准统一的,还是设计师随缘用PS拖拽出来的? 笔者偶然看到一篇文字:大家有没有想过,乐高包装的LEGO商标尺寸是 ...

  5. 开始研究DNN了。发现自己落伍了很多

    2年前就注意到DNN,但是由于很多事情,没有关注它的发展.回过头来,看看,一身冷汗中...... 决定用一个月的时间好好看看它,用它写几个东西. 下面把计划列在下面 1.看书(见附件) 2.利用现有源 ...

  6. 方向对了?MIT新研究:GPT-3和人类大脑处理语言的方式惊人相似

    来源:机器之心 本文约2700字,建议阅读6分钟 人和机器都是这样组织语言的. 「人工智能网络并没有试图直接模仿大脑,然而最终看起来像大脑一样,这在某种意义上表明,人工智能和自然之间发生了某种趋同演化 ...

  7. 华人科学家发现第四种传热方式!真空声子传热将改写物理教科书

    早在上中学时,我们就知道传热一共有三种方式,热传导.热对流.热辐射.如今,这一教科书上的知识要被改写了. 近期,一篇发表在<自然>杂志上的论文让不少传热学.物理学.量子力学等领域的科学家们 ...

  8. 爬取了同事的微博粉丝,结果发现300+涨粉中,真爱粉只有4个!

    事情是这样的,同事小A说他最近微博涨粉老快了,但是自己还是和以前一样就偶尔发发动态,看看新闻吃吃瓜,也没买啥涨粉包之类的. 小A说这话的时候稍显淡定,但是小一清楚的看到小A的嘴角微微上扬,不禁撇了撇嘴 ...

  9. 猿创征文|我的后端成长之路(985科班两年,我发现了大学正确打开方式)

    零.前言 当看到官方的这个活动的时候,我突然感到手指充满了力量,好像是我的键盘要向我尖端放电,谁还不是怀着满腔的热忱来写这篇文章帮助未来的学弟学妹们避坑呢?(其实是为了活动的奖励

最新文章

  1. 如何使用 Arthas 定位 Spring Boot 接口超时 ?
  2. 十大经典排序算法动画与解析,看我就够了!(配代码完全版)
  3. 前端UI框架《Angulr》入门
  4. matlab 图像二值化_推荐:为图像处理初学者设计的100个问题(含python实现代码)...
  5. mac环境下配置gradle\maven
  6. MTK 平台修改或查看USB驱动能力有三种方法
  7. 32岁男子沉迷网游十年离世 临终称真有意思
  8. C++/Qt 计算24点
  9. switch基本用法
  10. visual studio 错误:在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include StdAfx.h”?
  11. Word操作之Mathtype自动进行公式编号
  12. Python之私有属性和私有方法
  13. IMAX重开369家中国影院;康希诺辉瑞签署疫苗推广服务协议 | 美通企业日报
  14. 数字IC-1.8 子模块组建整模块-动态数码管设计代码实例
  15. python 滤波_[开发技巧]·Python极简实现滑动平均滤波(基于Numpy.convolve)
  16. prometheus grafana graylog 钉钉告警 短信告警 电话告警系统 PrometheusAlert
  17. 腾讯未来交通白皮书2.0
  18. 在线工具网站uzer.me使用Google Chrome浏览器打开,出现页面显示异常的解决办法
  19. 华南农业大学C语言程序设计课后习题(第五章)已修改
  20. Linux-ARM架构,全志H616香橙派开发笔记

热门文章

  1. sql--找含有制定字符列的表
  2. struts2的配置
  3. ssh错误 server not ready for puppeth err=“ssh: handshake failed: ssh: unable to authenticate... 解决方法
  4. java 日志输出 log4j 简介
  5. linux iostat 命令 统计信息 cpu 块设备 分区 io
  6. linux下几种反弹Shell方法的总结与理解
  7. linux 网络状态表 /proc/net/tcp 各项参数说明
  8. centos7 安装telnet服务
  9. golang 项目的目录结构
  10. gcc 编译器常用的命令行参数一览