此代码将抛出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的这一部分中的表格)
我的第一个问题是,为什么规范以这种方式编写?将值转换为更具表现力的选项(整数),而不是更原始的(int)更有意义吗?为了防止这种极其混乱的错误?
第二个问题是,您可以在Intellij的计算表达式中成功评估该表达式。结果将是赋值为null的wtf对象。是错误,还是指定它不符合JLS?
答案 0 :(得分:1)
为什么规范以这种方式编写?
我无法回答为什么,因为我没有编写规范。但我可以提出一个理由,为什么不应该
。当第二个和第三个参数具有不同类型,并且两种类型都可以转换为数字类型时,它们会经历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
将不自动取消装箱。出现这种差异是因为条件运算符指定在应用二进制数字提升之前检查相同的操作数类型。
答案 1 :(得分:0)
Integer wtf = 40 + (false ? Integer.valueOf("1") : 2));
中,必须生成一个 Integer 实例作为中间结果。