[英]NullPointerException through auto-boxing-behavior of Java ternary operator
I tripped across a really strange NullPointerException
the other day caused by an unexpected type-cast in the ternary operator.前几天我遇到了一个非常奇怪的
NullPointerException
这是由三元运算符中的意外类型转换引起的。 Given this (useless exemplary) function:鉴于这个(无用的示例)功能:
Integer getNumber() {
return null;
}
I was expecting the following two code segments to be exactly identical after compilation:我期望编译后以下两个代码段完全相同:
Integer number;
if (condition) {
number = getNumber();
} else {
number = 0;
}
vs.对比
Integer number = (condition) ? getNumber() : 0;
. .
Turns out, if condition
is true
, the if
-statement works fine, while the ternary opration in the second code segment throws a NullPointerException
.事实证明,如果
condition
为true
,则if
语句工作正常,而第二个代码段中的三元操作会抛出NullPointerException
。 It seems as though the ternary operation has decided to type-cast both choices to int
before auto-boxing the result back into an Integer
!?!似乎三元运算决定在将结果自动装箱回
Integer
之前将两个选项都类型转换为int
!?! In fact, if I explicitly cast the 0
to Integer
, the exception goes away.事实上,如果我显式地将
0
为Integer
,异常就会消失。 In other words:换句话说:
Integer number = (condition) ? getNumber() : 0;
is not the same as:不等同于:
Integer number = (condition) ? getNumber() : (Integer) 0;
. .
So, it seems that there is a byte-code difference between the ternary operator and an equivalent if-else
-statement (something I didn't expect).因此,三元运算符和等效的
if-else
语句之间似乎存在字节码差异(这是我没想到的)。 Which raises three questions: Why is there a difference?这就提出了三个问题:为什么会有差异? Is this a bug in the ternary implementation or is there a reason for the type cast?
这是三元实现中的错误还是类型转换的原因? Given there is a difference, is the ternary operation more or less performant than an equivalent
if
-statement (I know, the difference can't be huge, but still)?鉴于存在差异,三元运算的性能是否比等效的
if
语句更高或更低(我知道,差异不会很大,但仍然如此)?
The type of a conditional expression is determined as follows:
条件表达式的类型确定如下:
- If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.
如果第二个和第三个操作数具有相同的类型(可能是空类型),那么这就是条件表达式的类型。
- If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion
如果第二个和第三个操作数之一是原始类型 T,另一个的类型是应用装箱转换的结果
(§5.1.7) to T, then the type of the conditional expression is T.(§5.1.7) 到 T,则条件表达式的类型为 T。
The problem is that:问题在于:
Integer number = (condition) ? getNumber() : 0;
Forces an unboxing and reboxing of the result of getNumber().强制对 getNumber() 的结果进行拆箱和重新装箱。 This is because the false part of the ternary (0) is an integer, so it tries to convert the result of getNumber() to an int.
这是因为三元 (0) 的 false 部分是整数,因此它尝试将 getNumber() 的结果转换为 int。 Whereas the following does not:
而以下不是:
Integer number = (condition) ? getNumber() : (Integer) 0;
This is not a bug, just the way Java chose to do things.这不是错误,只是 Java 选择做事的方式。
This is how it is supposed to work.这就是它应该如何工作。 The ternary operator is not meant to be equivalent to a regular
if
statement.三元运算符并不意味着等同于常规
if
语句。 The bodies of if
and else
are statements , while the parts following ?
if
和else
的主体是语句,而后面的部分是?
and :
are expressions , that are required to evaluate to the same type.和
:
是表达式,需要计算为相同的类型。
Put another way: a = b ? c : d
换句话说:
a = b ? c : d
a = b ? c : d
is not supposed to be equivalent to if (b) a = c; else a = d;
a = b ? c : d
不应该等价于if (b) a = c; else a = d;
if (b) a = c; else a = d;
. . Instead,
b ? c : d
相反,
b ? c : d
b ? c : d
is an expression on its own, and the assignment of its result to a
won't affect the outcome. b ? c : d
本身就是一个表达式,将其结果赋值给a
不会影响结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.