Java的简写forms如果返回的对象之一为null,则返回NullPointerException

为什么此代码返回错误:java.lang.NullPointerException

Object obj = null; Long lNull = null; Long res = obj == null ? lNull : 10L; 

但是以下方式可以正常运行:

 Object obj = null; Long res = obj == null ? null : 10L; 

在第二种情况下,编译器可以推断出null必须是Long类型。 在第一种情况下,它没有 – 并假设表达式返回long 。 你可以看到这种情况(即修复它),如,

 Long res = obj == null ? lNull : (Long) 10L; 

它不会产生NullPointerException。

发生错误是因为在您的情况下,标准要求取消装箱的类型值 :

如果第二个和第三个操作数之一是原始类型T ,而另一个操作数的类型是对T应用装箱转换(第5.1.7节)的结果,那么条件表达式的类型是T

在你的情况下, Tlong ,因为10LlonglNullLonglNull boxing转换应用于long

标准进一步说明了这一点

如有必要,将对结果执行取消装箱转换。

这是导致exception的原因。 请注意,如果反转条件,则不再抛出exception:

 Long res = obj != null ? lNull : 10L; 

您可以通过明确要求Long而不是使用long来解决问题,即

 Long res = obj == null ? lNull : Long.valueOf(10L); 

JLS,第15.25节讨论了第二和第三个操作数类型的各种组合的条件运算符表达式的类型。 有许多表将所有相关组合中的两种类型映射到结果类型。

 3rd → long 2nd ↓ ... Long long ... null lub(null,Long) 

你的第一个例子有一个Long和一个long ,结果long 。 这需要将lNull取消装箱,这解释了NullPointerException

你的第二个例子有一个null 文字 (不是null变量)和一个long 文本 。 这导致“lub(null,Long)”或Long ,并且不执行拆箱,因此未观察到NPE。

您可以通过使用第一个示例或将10LLong来避免NPE,因为nullLong产生Long

 3rd → Long 2nd ↓ ... Long Long