这里有一点奇怪:
Integer oddity(boolean b1, boolean b2) {
return b1 ? 0 : b2 ? 1 : null;
}
这将失败并显示 NullPointerException
如果b1
和b2
是假的。但这:
Integer oddity(boolean b1) {
return b1 ? 0 : null;
}
当 b1
时不会抛出 NPE是假的。
这是为什么?
最佳答案
正如您所想,第一种情况中的 NullPointerException
是隐式拆箱的结果。这一切都如描述的那样in JLS Sec 15.25 ;但规则很复杂,并且有一些棘手的方面。
令人惊讶的是:
System.out.println(b ? 0 : null);
与
不一样Integer v = null;
System.out.println(b ? 0 : v);
- 第一种情况下的条件表达式的类型为
Integer
:0
被装箱为Integer.valueOf(0)
。因此,该语句将正常完成,并打印0
或null
。 - 第二种情况下的条件表达式的类型为
int
:v
已拆箱为v.intValue()
。因此,该语句要么打印0
,要么失败并返回NullPointerException
。
所以:问题中的第一个例子实际上是这两种情况的组合。插入隐式装箱和拆箱,就变成:
return Integer.valueOf(b1 ? 0 : (b2 ? Integer.valueOf(1) : null).intValue());
调用 intValue()
可能会失败;而问题中的第二个例子是:
return b1 ? Integer.valueOf(0) : null;
这不会失败。
如果您想返回 0、1 或 null,最小的更改就是显式地对 0
进行装箱:
return b1 ? Integer.valueOf(0) : b2 ? 1 : null;
这看起来很尴尬,因为 0 和 1 的表示方式不同。您也可以明确地将 1 装箱:
return b1 ? Integer.valueOf(0) : b2 ? Integer.valueOf(1) : null;
这有效,但很冗长,一些善意的同事(或者你,当你几个月后回来时,已经忘记了显式装箱的原因)将删除装箱,因为你不需要那个,对吧?
就个人而言 - 最近花了一些时间详细研究了条件运算符 - 我会选择完全避免它,并且不会冒险违反其奇怪的类型规则。
if (b1) {
return 0;
} else if (b2) {
return 1;
} else {
return null;
}
关于java - 使用时出现令人惊讶的 NullPointerException ? :,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48409983/