Java 使用时出现意外的NullPointerException?:

Java 使用时出现意外的NullPointerException?:,java,conditional-operator,language-specifications,Java,Conditional Operator,Language Specifications,这里有一点奇怪: Integer oddity(boolean b1, boolean b2) { return b1 ? 0 : b2 ? 1 : null; } 如果b1和b2为false,则此操作将失败,并出现NullPointerException。但这是: Integer oddity(boolean b1) { return b1 ? 0 : null; } 当b1为false时不抛出NPE 这是为什么?正如您可能想象的那样,第一种情况下的NullPointerExcep

这里有一点奇怪:

Integer oddity(boolean b1, boolean b2) {
  return b1 ? 0 : b2 ? 1 : null;
}
如果
b1
b2
为false,则此操作将失败,并出现
NullPointerException
。但这是:

Integer oddity(boolean b1) {
  return b1 ? 0 : null;
}
b1
为false时不抛出NPE


这是为什么?

正如您可能想象的那样,第一种情况下的
NullPointerException
是隐式取消装箱的结果。这就是所描述的一切;但规则很复杂,而且有一些棘手的方面

令人惊讶的是:

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;
}

好发现!拳击是错误的进一步证明;)