JDK 14中更好的NPE消息

我的2019年3月博客文章“ Java会出现更好的默认NullPointerException消息吗? ”是在尚未针对特定JDK版本针对更好的NullPointerException消息的JEP 草案编写时编写的。 此后,该JEP草案成为JEP 14的 目标 JEP 358(“ Helpful NullPointerExceptions”) 。 更好的是,初始实现( JDK-8218628已经在JDK 14分支中 ,并且可以在JDK 14 Early Access Build Build 20(2019/10/23)中使用

在本文中,我将针对JDK 14 Early Access Build 20运行先前文章中介绍的示例代码 ,以演示现在提供的其他详细信息。 要查看为故意引入导致NullPointerException的各种情况而编写的示例代码,请参阅前面的文章或查看GitHub上源代码

下载JDK 14 Early Access Build 20并按其路径指向该文件后,运行java -version时会看到以下内容:

 openjdk version "14-ea" 2020 - 03 - 17  OpenJDK Runtime Environment (build 14 -ea+ 20 - 879 )  OpenJDK 64 -Bit Server VM (build 14 -ea+ 20 - 879 , mixed mode, sharing) 

在正确配置了JDK 14 Early Access Build 20之后 ,我重新构建了前面提到源代码 ,然后使用Java启动器重新运行了该代码,而没有任何新选项。 该输出(如下所示)与以前的JDK版本的输出没有实质性差异。

 =========================================  | # | # 1 : Element [ null boolean array | ] on : Element [ 0 ] on  =========================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateFirstExampleIndexAccessOnNullBooleanArray(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =================================  | # | # 2 : .length on null boolean [] |  =================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateSecondExampleLengthOnNullBooleanArray(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =======================================  | # | # 3 : Assigning float : Assigning to null float [] |  =======================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateThirdExampleAssigningValueToElementOfNullFloatArray(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ======================================  | # | # 4 : Accessing field on null object | : Accessing field on object |  ======================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateFourthExampleAccessInstanceFieldOfNullObject(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ===================  | # | # 5 : throw null ; | ; |  ===================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateFifthExampleThrowingConstantNull(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ================================================  | # | # 6 : Method invocation on null instance field | : Method invocation on  ================================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateSixthExampleMethodInvocationOnNullInstanceField(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =============================================  | # | # 7 : () on null instance field | () on synchronized () on instance field |  =============================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateSeventhExampleSynchronizedNullInstanceField(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ==========================================================================  | >>> Null Lost in Long Series of Method Invocations in Single Statement |  ==========================================================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateNullLostInSeriesOfMethodInvocationsInSingleStatement(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =======================================================  | >>> Null Lost in Dereferenced Constructor Arguments |  =======================================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateNullLostInConstructorAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ==================================================  | >>> Null Lost in Dereferenced Method Arguments |  ==================================================  java.lang.NullPointerException 
  at dustin.examples.npe.NpeDemo.demonstrateNullLostInMethodAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source) 

如以上输出所示,即使使用新的JDK 14 Early Access Build 20,当我正常运行应用程序时,也看不到有关NullPointerException的任何新的详细信息。 我包含了此输出,以表明需要一个特殊的标志来启用更详细的NullPointerException ,并使其更方便地比较带有和不带有其他详细信息的输出。 下一个输出清单显示了将Java启动器传递给标志-XX:+ShowCodeDetailsInExceptionMessages时提供的其他详细信息:

 =========================================  | # | # 1 : Element [ null boolean array | ] on : Element [ 0 ] on  =========================================  java.lang.NullPointerException: Cannot load from byte / boolean array because java.lang.NullPointerException: Cannot load from array because "<local1>" is null 
  at dustin.examples.npe.NpeDemo.demonstrateFirstExampleIndexAccessOnNullBooleanArray(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =================================  | # | # 2 : .length on null boolean [] |  =================================  java.lang.NullPointerException: Cannot read the array length because "<local1>" is null 
  at dustin.examples.npe.NpeDemo.demonstrateSecondExampleLengthOnNullBooleanArray(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =======================================  | # | # 3 : Assigning float : Assigning to null float [] |  =======================================  java.lang.NullPointerException: Cannot store to array because "<local1>" is null array because java.lang.NullPointerException: Cannot store to float array because 
  at dustin.examples.npe.NpeDemo.demonstrateThirdExampleAssigningValueToElementOfNullFloatArray(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ======================================  | # | # 4 : Accessing field on null object | : Accessing field on object |  ======================================  java.lang.NullPointerException: Cannot read field "nullInstanceField" because "<local1>" is null 
  at dustin.examples.npe.NpeDemo.demonstrateFourthExampleAccessInstanceFieldOfNullObject(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ===================  | # | # 5 : throw null ; | ; |  ===================  java.lang.NullPointerException: Cannot throw exception because "null" is null 
  at dustin.examples.npe.NpeDemo.demonstrateFifthExampleThrowingConstantNull(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ================================================  | # | # 6 : Method invocation on null instance field | : Method invocation on  ================================================  java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "this.nullInstanceField" is null 
  at dustin.examples.npe.NpeDemo.demonstrateSixthExampleMethodInvocationOnNullInstanceField(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =============================================  | # | # 7 : () on null instance field | () on synchronized () on instance field |  =============================================  java.lang.NullPointerException: Cannot enter synchronized block because "this.nullInstanceField" is null 
  at dustin.examples.npe.NpeDemo.demonstrateSeventhExampleSynchronizedNullInstanceField(Unknown Source) 
  at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ==========================================================================  | >>> Null Lost in Long Series of Method Invocations in Single Statement |  ==========================================================================  java.lang.NullPointerException: Cannot invoke "dustin.examples.npe.DysfunctionalLocation$Province.getCity()" because the return value of "dustin.examples.npe.DysfunctionalLocation$Nation.getProvince()" is null 
  at dustin.examples.npe.NpeDemo.demonstrateNullLostInSeriesOfMethodInvocationsInSingleStatement(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  =======================================================  | >>> Null Lost in Dereferenced Constructor Arguments |  =======================================================  java.lang.NullPointerException: Cannot invoke "java.lang.Long.longValue()" because "<local6>" is null 
  at dustin.examples.npe.NpeDemo.demonstrateNullLostInConstructorAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source)  ==================================================  | >>> Null Lost in Dereferenced Method Arguments |  ==================================================  java.lang.NullPointerException: Cannot invoke "java.lang.Long.longValue()" because "<local6>" is null 
  at dustin.examples.npe.NpeDemo.demonstrateNullLostInMethodAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) 
  at dustin.examples.npe.NpeDemo.main(Unknown Source) 

JEP 358解释了使用此标志来查看其他NullPointerException详细信息:“可以使用新的boolean命令行选项-XX { + | - } ShowCodeDetailsInExceptionMessages -XX { + | - } ShowCodeDetailsInExceptionMessages 。 该选项将首先具有默认值' false ',以便不打印消息。 它旨在在以后的版本中默认情况下在异常消息中启用代码详细信息。” 如我们所见,此功能默认情况下最初处于关闭状态,但是有计划在将来启用更详细的NullPointerException消息。

最近的一条Tweet问了一个问题:“如果字节码不包含变量名,它将如何工作?” 这个问题通过提供一个具体的例子来继续:“假设我们有像Object a = ....; a.getName(); //NPE这样的代码Object a = ....; a.getName(); //NPE Object a = ....; a.getName(); //NPE Object a = ....; a.getName(); //NPE NPE会Object a = ....; a.getName(); //NPE哪种消息?” 尽管在前面显示的一系列测试中都包含了一个示例,但我认为我将在此提供一个针对性更强的示例来回答该问题。 下一个代码清单(也在GitHub上提供 )显示了改编自Tweet中使用的示例的代码。

 package dustin.examples.npe;  /** 
  * Simple demonstration to answer Tweet-ed question 
  * "How it will work if bytecode doesn't contain variable names?" 
  * ( https://twitter.com/2doublewhiskey/status/1180365953240055809 ). 
  */  public class TwoDoubleWhiskeyTweetExample  { 
    public static void main( final String[] arguments) 
    { 
       final Person person = null ; 
       person.getName(); //NPE 
    }    
    public static class Person 
    { 
       private String name; 
       public Person( final String newName) 
       { 
          name = newName; 
       } 
       public String getName() 
       { 
          return name; 
       } 
    }  } 

下一个屏幕快照显示了使用JDK 14 Early Access Build 20(不带java启动器标志-XX:+ShowCodeDetailsInExceptionMessages运行此简单应用程序的结果。

如屏幕快照所示,在JDK 14 Early Access Build 20中使用-XX:+ShowCodeDetailsInExceptionMessages标志可提供与此简单NullPointerException示例相关的其他详细信息:“无法调用” dustin.examples.npe.TwoDoubleWhiskeyTweetExample $ Person.getName() ”,因为“ <local1> ”为空”

GitHub上提供了一个更简单甚至更接近Tweet-ed问题中提供的原始示例的示例。

JEP 358 (“ 有用的NullPointerExceptions ”)可能不像新JDK发行版中的其他一些JEP那样浮华,但最终可能是每天为Java开发人员提供比其一些浮华同行更高的价值 。 有许多示例将对您有所帮助,JEP本身以及本文引用的我的代码示例中都阐明了许多示例情况。

翻译自: https://www.javacodegeeks.com/2019/10/better-npe-messages-in-jdk-14.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值