我的一个学生在使用三元运算符时会得到空指针异常,有时会导致null.我想我理解这个问题,但似乎是因为类型推断不一致所致.换句话说,我觉得这里的语义不一致,错误应该可以避免,而不改变他的方法.
这个问题类似于,但与另一个关于三元运算符的问题不同.在那个问题中,null Integer必须强制为int,因为函数的返回值是int.但是,我学生的代码并非如此.
这段代码运行正常:
Integer x = (5>7) ? 3 : null;
Run Code Online (Sandbox Code Playgroud)
x的值为null.没有NPE.在这种情况下,编译器可以确定三元运算符的结果需要是Integer,因此它将3(一个int)转换为Integer而不是将null转换为int.
但是,运行此代码:
Integer x = (5>7) ? 3 : (5 > 8) ? 4 : null;
Run Code Online (Sandbox Code Playgroud)
导致NPE.发生这种情况的唯一原因是因为null被转换为int,但这并不是必需的,并且似乎与第一位代码不一致.也就是说,如果编译器可以推断第一个snipet三元运算符的结果是整数,为什么不能在第二种情况下这样做呢?第二个三元表达式的结果必须是整数,并且由于该结果是第一个三元运算符的第二个结果,因此第一个三元运算符的结果也应该是整数.
另一个snipet工作正常:
Integer three = 3;
Integer x = (5>7) ? three : (5 > 8) ? three+1 : null;
Run Code Online (Sandbox Code Playgroud)
在这里,编译器似乎能够推断出两个三元运算符的结果都是一个整数,所以不强制将null转换为int.
biz*_*lop 13
关键是条件运算符是右关联的.确定条件表达式的结果类型的规则非常复杂,但归结为:
(5 > 8) ? 4 : null进行评估,第二个操作数是一个int,第三个是null,如果我们在表中查找它,该表达式的结果类型是Integer.(换句话说:因为其中一个操作数是null,这被视为参考条件表达式)(5>7) ? 3 : <previous result>进行评估,这意味着在上面链接的表中,我们需要查找第二个操作数int和第三个操作数的结果类型Integer:它是int.这意味着<previous result>需要取消装箱并失败NPE.那么为什么第一个案例呢?
在那里,我们已经得到了(5>7) ? 3 : null;,因为我们已经看到了,如果第二个操作数int和第三个是null,结果类型为Integer.但是我们将它分配给一个Integer类型的变量,因此不需要拆箱.
但是这只发生在null文字中,下面的代码仍然会抛出一个NPE,因为操作数类型int并Integer导致数字条件表达式:
Integer i = null;
Integer x = (5>7) ? 3 : i;
Run Code Online (Sandbox Code Playgroud)
总结一下:它有一种逻辑,但它不是人的逻辑.
Integer,则结果为a Integer.int而另一个是Integer,则结果是a int.null引用),则结果为a Integer.| 归档时间: |
|
| 查看次数: |
1475 次 |
| 最近记录: |