双三元整数启动会导致空指针

时间:2014-08-05 09:42:58

标签: java

为什么将x设置为null是正确的:

boolean condition1 = false;
Integer x = condition1 ? 1 : null;

这很好,x设置为2:

boolean condition1 = false, condition2 = true;
Integer x = condition1 ? 1 : condition2? 2 : null;

但是,x应该设置为null会导致java.lang.NullPointerException

boolean condition1 = false, condition2 = false;
Integer x = condition1 ? 1 : condition2 ? 2 : null;

解决方案是使用:

Integer x = condition1 ? (Integer)1 : condition2 ? 2 : null;

但我不清楚为什么单个三元运算符工作正常,但不是双精度。

1 个答案:

答案 0 :(得分:1)

(在你完成一些拆包后我仍然认为这是duplicate,但是嘿......)

将一个陈述扩展为两个:

// Not exactly the same, but close...
Integer tmp = condition2 ? 2 : null;
Integer x = condition1 ? 1 : (int) tmp;

这并不完全相同,因为即使condition2 ? 2 : null为假,它也会评估condition1 - 您可以使用方法调用对其进行建模,但在您担心的情况下,{{1} }和condition1都是假的。

现在,你可能会问为什么我们在这里得到了演员condition2。这是因为JLS 15.25.2

  

数字条件表达式的类型确定如下:

     
      
  • ...
  •   
  • 如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,则条件表达式的类型为T. / LI>   
  • ...
  •   

我们有intint,因此匹配Integer ...并且“内部”条件表达式的结果在必要时被取消装箱......这就是造成这种情况的原因一个问题。

T = int转换为1会对此进行更改,以便外部表达式的类型也为Integer(因为第二个和第三个操作数都具有类型Integer)所以没有拆箱。

请注意,在我们的扩展中,Integertmp,它实际上是“内部”条件表达式的类型,因为第三个操作数的类型是null类型,而不是{ {1}}。你也可以只用一个条件使它失败:

Integer

基本上,分别具有类型IntegerInteger bang = false ? 2 : (Integer) null; 的第二个和第三个操作数的条件运算符将执行第三个操作数的取消装箱(结果是类型int),但是条件具有Integerint类型的第二个和第三个操作数的运算符将分别 unbox,结果类型为int