此代码将抛出 NPE:
Integer wtf = false ? 1 : (Integer) null;
事实是,如果第二个或第三个操作数是 int,那么另一个也将被转换为 int。 (根据JLS https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25这部分表格)
我的第一个问题是,为什么规范是这样写的?将值转换为更具表现力的选项(整数)比转换为更原始的选项(整数)更有意义吗?为了防止这种极其困惑的错误?
第二个问题是,您可以在 Intellij 的求值表达式中成功求值该表达式。结果将是分配了 null 的 wtf 对象。它是错误,还是某处指定它不符合 JLS?
最佳答案
why is specification written in this way?
我无法回答为什么,因为我没有编写规范。但我可以提出一个不应该的原因。
当第二个和第三个参数是不同类型,并且两种类型都可以转换为数字类型时,它们会经过binary numeric promotion。 .这与其他采用数字操作数的运算符相同,例如+
。
如果您尝试添加一个 int
和一个 Integer null
,您可以获得相同的 NPE:
System.out.println(1 + (Integer) null);
在这种情况下,您无法通过将 1 装箱到 Integer.valueOf(1)
来做任何有用的事情。
如果在 +
和 ?:
运算符 (*) 之间以不同方式处理数字类型,将会不一致。并且条件运算符需要采用某种形式的二进制数字提升,以便能够处理不同类型的原始操作数,例如int
和 double
。
一目了然specification for the conditional operator应该让你相信它的类型处理已经疯狂复杂了(见表 15.25-A 到 E),所以它不应该变得更复杂。
不幸的是,您能够以这种方式搬起石头砸自己的脚;但语言就是这样。
我认为这里的问题在于将自动装箱作为一种通用语言功能;没有它,就不会有这样的问题,因为您必须自己进行拆箱。
(*) 实际上,它的行为确实有点不同。例如,(Integer) null + (Integer) null
将自动拆箱,而 condition ? (Integer) null : (Integer) null
不会自动拆箱。出现这种差异是因为条件运算符指定在应用二进制数字提升之前检查相同的操作数类型。
关于java 三元运算符内部 + intellij 评估表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50606175/