在Java语言中,处理空指针往往是一件很头疼的事情,一不小心,说不定就搞出个线上Bug,让你的绩效考核拿到3.25。最近新出的Java14,相信大家都有所耳闻,那么今天就来看看,面对NullPointerException,Java14有哪些更好的处理方式呢?
1.传统的 NullPointerException
我们编码过程中呢,经常会使用链式调用的方式来写代码,这样写起来很方便,也很清晰,但是,一旦出现NullPointerException,那就头大了,因为你很难知道异常是在什么时候开始发生的。 举个简单的例子,就比如下面的代码,要找到公司某个员工的户籍所在地,我们这样来调用
String city = employee.getDetailInfos().getRegistryAddress().getCity();
在链式调用的过程中,如果employee
, getDetailInfos()
,或者 getRegistryAddress()
为空,JVM就会抛出 NullPointerException
, 那么导致异常的根本原因是什么?如果不使用调试器,很难确定哪个变量为空。而且,JVM也只会打印导致异常的方法、文件名和行号,仅此而已。 那么下面,我将带大家了解Java 14如何通过 JEP 358
解决这个问题。
2.增强型 NullPointerException
SAP在2006年为其商业JVM实现了增强型的
-XX:+ShowCodeDetailsInExceptionMessages
2.1 详细的异常信息
考虑在激活 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由两部分组成详细的异常消息。第一部分表示失败的操作,这是引用为
Cannot invoke "String.toLowerCase()" because the return value of "getEmailAddress()" is null
为了生成异常消息,JEP 358 重构了将空引用推送到操作数堆栈上的部分源代码。
3. 技术方面
现在我们已经很好地理解了如何使用增强的
首先,只有当JVM本身抛出一个
其次,**JEP 358 ** 懒汉式地计算消息,这意味着只有当我们打印异常消息时才调用增强的NullPointerException,而不是当异常发生时就调用。因此,对于通常的JVM流程不应该有任何性能影响,在那里我们可以捕获并重新抛出异常,因为咱并不会只想打印异常消息。
最后,详细的异常消息可能包含源代码中的局部变量名。因此,我们可以认为这是一个潜在的安全风险。但是,只有在运行使用激活的
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,我们可以很快速的定位代码问题的原因所在,更快的调试代码,节约时间,提高效率。