为什么三元运算符意外地投出整数?

我已经看到它在某处讨论了下面的代码导致obj是一个Double ,但它从左侧打印200.0

 Object obj = true ? new Integer(200) : new Double(0.0); System.out.println(obj); 

结果:200.0


但是,如果在右侧放置不同的对象,例如BigDecimal ,则obj的types应该是Integer

 Object obj = true ? new Integer(200) : new BigDecimal(0.0); System.out.println(obj); 

结果:200


我认为这样做的原因是将左手边转换为double精度,就像integer / double精度比较和计算一样,但左右两边并不以这种方式相互作用。

为什么会发生?

您需要阅读Java语言规范的第15.25节 。

尤其是:

否则,如果第二个和第三个操作数具有可转换types(§5.1.8)为数字types,则有以下几种情况:

  • 如果其中一个操作数是byte或Bytetypes,另一个是short或Shorttypes,则条件expression式的types很短。
  • 如果其中一个操作数的types是T,其中T是byte,short或char,另一个操作数是types为int的常量expression式,其值可以用T表示,则条件expression式的types为T.
  • 如果其中一个操作数的types是Byte,另一个操作数是inttypes的常量expression式,其值可以用bytetypes表示,那么条件expression式的types就是byte。
  • 如果其中一个操作数的types为Short,而另一个操作数的types为int的常量expression式的值可以用shorttypes表示,则条件expression式的types很短。
  • 如果其中一个操作数是types的, 字符和另一个操作数是types为int的常量expression式,其值可以在chartypes中表示,则条件expression式的types为char。
  • 否则,对操作数types应用二进制数字提升(第5.6.2节),并且条件expression式的types是第二个和第三个操作数的提升types。 请注意,二进制数字提升会执行拆箱转换(§5.1.8)和值集转换(§5.1.13)。

所以应用了二进制数字提升 ,其开始于:

当运算符将二进制数字提升应用于一对操作数时,每个操作数都必须表示一个可转换为数值types的值,应用以下规则,按照顺序使用扩展转换(第5.1.2节)根据需要转换操作数:

  • 如果任何操作数是引用types,则执行拆箱转换(§5.1.8)。 然后:
  • 如果其中一个操作数的types是double,另一个则转换为double。

这正是这里发生的事情 – 参数types分别转换为intdouble ,第二个操作数(原始expression式中的第三个操作数)是doubletypes的,所以总体结果types是double

在条件运算符中进行数值转换? :

在条件运算符a ? b : c ,如果bc都是不同的数字types,则在编译时应用以下转换规则以使它们的types相等 ,顺序如下:

  • types被转换为相应的原始types,这被称为拆箱

  • 如果一个操作数是一个常数 int (在拆箱前不是Integer ),其值可以在另一个types中表示,则该int操作数转换为另一个types。

  • 否则,较小的types转换为下一个更大的types,直到两个操作数具有相同的types。 转换顺序是:
    byte – > short – > int – > long – > float – > double
    char – > int – > long – > float – > double

最终,整个条件expression式获得其第二个和第三个操作数的types。

例子:
如果你把charshort结合起来,expression式就变成int
如果将IntegerInteger相结合,则expression式变为Integer
如果将final int i = 5Character ,则expression式将变为char
如果将shortfloat结合使用,则expression式将变为float

在问题的例子中,200从Integer转换为double ,0.0从Double拆箱变为double ,整个条件expression式变为double ,最终装箱成Double因为objObjecttypes的。