我在某处看到过讨论,以下代码导致
obj
成为 Double
,但它从左侧打印 200.0
。
Object obj = true ? new Integer(200) : new Double(0.0);
System.out.println(obj);
结果:200.0
但是,如果您在右侧放置不同的物体,例如
BigDecimal
,obj
的类型应该是Integer
。
Object obj = true ? new Integer(200) : new BigDecimal(0.0);
System.out.println(obj);
结果:200
我认为这样做的原因与将左侧投射到
double
有关,就像integer
/double
比较和计算一样,但这里左侧和右侧确实如此不要以这种方式互动。
为什么会出现这种情况?
您需要阅读Java 语言规范第 15.25 节。
特别是:
否则,如果第二个和第三个操作数具有可转换(§5.1.8)为数字类型的类型,则有几种情况:
- 如果其中一个操作数为 byte 或 Byte 类型,另一个操作数为 Short 或 Short 类型,则条件表达式的类型为 Short。
- 如果其中一个操作数是 T 类型,其中 T 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式,其值可以用 T 类型表示,则 > - 条件表达式的类型为 T .
- 如果其中一个操作数是 Byte 类型,另一个操作数是 int 类型的常量表达式,其值可以用 byte 类型表示,则条件表达式的类型为 byte。
- 如果其中一个操作数是 Short 类型,另一个操作数是 int 类型的常量表达式,其值可以用 Short 类型表示,则条件表达式的类型是 Short。
- 如果其中一个操作数是类型;字符,另一个操作数是 int 类型的常量表达式,其值可以用 char 类型表示,则条件表达式的类型为 char。
- 否则,将对操作数类型应用二进制数值提升(第 5.6.2 节),并且条件表达式的类型是第二个和第三个操作数的提升类型。请注意,二进制数字提升执行拆箱转换(第 5.1.8 节)和值集转换(第 5.1.13 节)。
因此应用二进制数字提升,其开头为:
当运算符对一对操作数应用二进制数字提升时,每个操作数必须表示一个可转换为数字类型的值,以下规则按顺序适用,使用扩展转换(第 5.1.2 节)将操作数转换为必要:
- 如果任何操作数是引用类型,则执行拆箱转换(第 5.1.8 节)。然后:
- 如果其中一个操作数为 double 类型,则另一个将转换为 double。
这正是这里发生的情况 - 参数类型分别转换为
int
和 double
,第二个操作数(原始表达式中的第三个)的类型为 double
,因此总体结果类型为 double
.
在条件运算符中,如果两个不同的数字类型,则以下转换规则在编译
时应用,以使它们的类型相等,顺序为:
类型被转换为相应的原始类型,这称为
拆箱。 如果一个操作数是 constant
a
(拆箱前不是 ?
),其值可以用另一种类型表示,则
b
操作数将转换为另一种类型。
否则,较小的类型将转换为下一个较大的类型,直到两个操作数具有相同的类型。转换顺序为:
:
-> c
b
-> c
-> int
Integer
int
->
byte
-> short
-> int
-> long
最终整个条件表达式获得其第二个和第三个操作数的类型。
示例:如果将
float
与 double
组合,则表达式变为 char
。如果将
int
long
组合,则表达式变为 float
。如果将
double
与
char
组合,则表达式变为
short
。int
与
Integer
组合,则表达式变为 Integer
。
在问题的示例中,200从
Integer
转换为
final int i = 5
Character
拆箱为char
,整个条件表达式变成short
,最终被装箱为float
,因为
float
属于类型
Integer
。
示例:
double