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.2)转换操作数:

  • 如果任何操作数为引用类型,则执行取消装箱转换(§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:是的。编译器决定什么是