繁体   English   中英

为什么三元运算符会意外地转换整数?

[英]Why does the ternary operator unexpectedly cast integers?

我在某处看到它讨论以下代码导致objDouble ,但它从左侧打印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。
  • 如果操作数之一是类型; Character 和另一个操作数是一个 int 类型的常量表达式,其值可以用 char 类型表示,则条件表达式的类型为 char。
  • 否则,将二进制数值提升(第 5.6.2 节)应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。 请注意,二进制数字提升执行拆箱转换(第 5.1.8 节)和值集转换(第 5.1.13 节)。

因此应用了二进制数字提升,其开头为:

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

  • 如果任何操作数是引用类型,则执行拆箱转换(第 5.1.8 节)。 然后:
  • 如果任一操作数的类型为 double,则另一个将转换为 double。

这正是这里发生的情况 - 参数类型分别转换为intdouble ,第二个操作数(原始表达式中的第三个)是double类型,因此整体结果类型为double

条件运算符中的数字转换 ?

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

  • 这些类型被转换为它们对应的原始类型,这称为unboxing

  • 如果一个操作数是一个常量int (拆箱前不是Integer ),其值可以用另一种类型表示,则int操作数将转换为另一种类型。

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

最终整个条件表达式得到它的第二个和第三个操作数的类型。

例子:
如果将charshort结合使用,则表达式将变为int
如果将IntegerInteger结合使用,则表达式将变为Integer
如果将final int i = 5Character ,则表达式变为char
如果将shortfloat结合使用,则表达式将变为float

在问题的示例中, 200 从Integer转换为double , 0.0 从Double拆箱为double ,整个条件表达式变为double ,最终被装箱为Double因为objObject类型。

例子:

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.

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM