2

这里有点奇怪:

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 。

为什么是这样?

4

1 回答 1

2

正如您可能想象的NullPointerException那样,第一种情况是隐式拆箱的结果。这一切都在 JLS Sec 15.25中描述;但是规则很复杂,并且有一些棘手的方面。

这里令人惊讶的是:

System.out.println(b ? 0 : null);

不一样

Integer v = null;
System.out.println(b ? 0 : v);
  • 第一种情况下的条件表达式具有类型Integer0被装箱为Integer.valueOf(0)。因此,该语句将正常完成,打印0null
  • 第二种情况下的条件表达式具有类型int: vis unboxed to 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;
}
于 2018-01-23T20:07:52.060 回答