为什么三元运算符意外地投出整数?
我已经看到它在某处讨论了下面的代码导致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分别转换为int
和double
,第二个操作数(原始expression式中的第三个操作数)是double
types的,所以总体结果types是double
。
在条件运算符中进行数值转换? :
在条件运算符a
?
b
:
c
,如果b
和c
都是不同的数字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。
例子:
如果你把char
和short
结合起来,expression式就变成int
。
如果将Integer
与Integer
相结合,则expression式变为Integer
。
如果将final int i = 5
与Character
,则expression式将变为char
。
如果将short
和float
结合使用,则expression式将变为float
。
在问题的例子中,200从Integer
转换为double
,0.0从Double
拆箱变为double
,整个条件expression式变为double
,最终装箱成Double
因为obj
是Object
types的。