java三元运算符内部结构+ intellij计算表达式

时间:2018-05-30 13:37:13

标签: java intellij-idea ternary-operator jls

此代码将抛出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?

2 个答案:

答案 0 :(得分:1)

  

为什么规范以这种方式编写?

我无法回答为什么,因为我没有编写规范。但我可以提出一个理由,为什么不应该

当第二个和第三个参数具有不同类型,并且两种类型都可以转换为数字类型时,它们会经历binary numeric promotion。这与采用数字操作数的其他运算符相同,例如+

如果您尝试添加intInteger null,则可以获得相同的NPE:

System.out.println(1 + (Integer) null);

在这种情况下,您无法通过将1加入Integer.valueOf(1)来执行任何有用的操作。

如果+?:运算符(*)之间的数值类型处理方式不同,则会不一致。并且条件运算符需要使用二进制数字提升的某种形式,以便能够处理不同类型的原始操作数,例如, intdouble

瞥一眼specification for the conditional operator应该让你相信它的类型处理已经疯狂复杂了(见表15.25-A到E),所以它不应该被制作出来更是如此。

很遗憾,你可以用这种方式射击自己;但这就是语言的方式。

我认为这里的问题是自动装箱作为一般语言功能;没有它,就不会有这样的问题,因为你必须自己进行拆箱。

(*)实际上,它确实表现得有点不同。例如,(Integer) null + (Integer) null将自动取消装箱,而condition ? (Integer) null : (Integer) null自动取消装箱。出现这种差异是因为条件运算符指定在应用二进制数字提升之前检查相同的操作数类型。

答案 1 :(得分:0)

  • 我想原因是效率和简单性:更少的内存和直接访问而不是通过 Integer 包装器对象。否则,e。 G。在Integer wtf = 40 + (false ? Integer.valueOf("1") : 2));中,必须生成一个 Integer 实例作为中间结果。
    通过装箱/取消装箱,您所指的表格变得必要Java 5.在Java 1.4中,不允许对第二个和第三个操作数同时使用 int Integer
  • 是的,这是一个错误,因为它违反了JLS。