Java 为什么三元运算符意外地强制转换整数?
我在某个地方看到过这样的讨论:下面的代码导致Java 为什么三元运算符意外地强制转换整数?,java,casting,ternary-operator,conditional-operator,Java,Casting,Ternary Operator,Conditional Operator,我在某个地方看到过这样的讨论:下面的代码导致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); Sys
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
进行比较和计算一样,但在这里,左手侧和右手侧不会以这种方式相互作用
为什么会发生这种情况?你需要阅读
特别是:
否则,如果第二个和第三个操作数的类型可转换为数值类型(§5.1.8),则有几种情况:
- 如果其中一个操作数的类型为byte或byte,而另一个操作数的类型为short或short,则条件表达式的类型为short
- 如果其中一个操作数为T类型,其中T为字节、短字符或字符,而另一个操作数为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.8)。然后:
- 如果其中一个操作数的类型为double,则另一个操作数将转换为double
int
和double
,第二个操作数(原始表达式中的第三个)的类型为double
,因此条件运算符中的整体结果类型为double数值转换:
在条件运算符a
?
b
:
c
中,如果b
和c
都是不同的数字类型,则在编译时应用以下转换规则以使它们的类型按顺序相等:
- 这些类型将转换为相应的基本类型,称为取消装箱
- 如果一个操作数是一个常数
int
(在取消装箱之前不是Integer
),其值可在另一种类型中表示,则将int
操作数转换为另一种类型
- 否则,较小的类型将转换为下一个较大的类型,直到两个操作数具有相同的类型。转换顺序为:
byte
->short
->int
->long
->float
->double
char
->int
->long
->float
->double
最终,整个条件表达式将获得其第二个和第三个操作数的类型
示例:
如果将char
与short
组合,表达式将变为int
如果将整数
与整数
组合,表达式将变为整数
如果将final int i=5
与字符
组合,表达式将变为char
如果将short
与float
组合,表达式将变为float
在问题的示例中,200从整数
转换为双精度
,0.0从Double
解封为Double
,整个条件表达式变为Double
,最终被装箱为Double
,因为obj
类型为Object示例:
public static void main(String[] args) {
int i = 10;
int i2 = 10;
long l = 100;
byte b = 10;
char c = 'A';
Long result;
// combine int with int result is int compiler error
// result = true ? i : i2; // combine int with int, the expression becomes int
//result = true ? b : c; // combine byte with char, the expression becomes int
//combine int with long result will be long
result = true ? l : i; // success - > combine long with int, the expression becomes long
result = true ? i : l; // success - > combine int with long, the expression becomes long
result = true ? b : l; // success - > combine byte with long, the expression becomes long
result = true ? c : l; // success - > char long with long, the expression becomes long
Integer intResult;
intResult = true ? b : c; // combine char with byte, the expression becomes int.
// intResult = true ? l : c; // fail combine long with char, the expression becomes long.
}
我不精通Java,但要问的正确问题是“三元条件表达式的类型是什么?”我必须承认这是相当混乱的东西。当我在NetBeans中运行这个时,我真的很惊讶,obj.getClass()
显示了Double
。见鬼,老兄。加·乔恩·斯基特比我抢先一步:)+1@VivinPaliath是的,我也是,但那没关系,因为我正要从另一个关于三元运算符的问题中引用他的话;-)虽然我很高兴有关于它的文档,但我看不出其中的任何地方有什么原因(但我肯定我看得不太清楚)。在我看来,这是一个赋值,不需要二进制数字升级,我是不是遗漏了什么?@HXCaine:对于相同类型但基本类型的情况,你希望它做什么?请记住,表达式的类型与赋值部分是分开的。@HXCaine:是的。编译器决定什么是