为什么这段代码返回错误: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
,而另一个操作数的类型是将装箱转换 (§5.1.7( 应用于T
的结果,则条件表达式的类型为T
个。
在你的情况下,T
是long
的,因为10L
是long
的,lNull
是Long
的,即将装箱转换应用于long
的结果。
该标准进一步指出,
如有必要,将对结果执行拆箱转换。
这就是导致异常的原因。请注意,如果反转条件,将不再引发异常:
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。
你可以通过使用你的第一个示例或通过将10L
转换为Long
来避免 NPE,因为null
和Long
产生一个Long
。
3rd → Long 2nd ↓ ... Long Long