这有点古怪:
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。
为什么会这样?
答案 0 :(得分:2)
正如您可能想象的那样,第一种情况下的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;
}