【问题标题】:Why is the result of conditional operator opposite of expected? [duplicate]为什么条件运算符的结果与预期相反? [复制]
【发布时间】:2014-12-24 09:04:37
【问题描述】:
Object myObject = true ? new Integer(25) : new Double(25.0);

System.out.println(myObject);

奇怪的是,它输出的是 25.0 而不是 25

怎么了?

【问题讨论】:

  • 大胆猜测:拆箱后重新装箱;在拆箱阶段,您的int 将转换为double。例如,如果你这样做new Integer(13),我打赌结果将是13.0

标签: java operators


【解决方案1】:

您的代码按预期返回第二个操作数 (new Integer(25)),但由于以下规则,它会将其转换为 Double

JLS 15.25 是这样说的:

如果第二个和第三个操作数的类型可以转换(第 5.1.8 节)为数字类型,那么有几种情况:

  • 如果其中一个操作数是 byte 或 Byte 类型,而另一个是 short 或 Short 类型,则条件表达式的类型为 short。
  • 如果其中一个操作数是 T 类型,其中 T 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式(第 15.28 节),其值可在类型 T 中表示,则条件表达式是 T。
  • 如果其中一个操作数是 T 类型,其中 T 是 Byte、Short 或 Character,而另一个操作数是 int 类型的常量表达式(第 15.28 节),其值可在作为结果的 U 类型中表示对T进行拆箱转换,则条件表达式的类型为U。
  • 否则,二进制数值提升(第 5.6.2 节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型
    请注意,二进制数字提升执行值集转换(第 5.1.13 节)并可能执行拆箱转换(第 5.1.8 节)。

还有数字推广:

5.6.2。二进制数字提升

当运算符对一对操作数应用二进制数值提升时,每个操作数都必须表示一个可转换为数值类型的值,按顺序适用以下规则:

如果任何操作数是引用类型,则对其进行拆箱转换(第 5.1.8 节)。

加宽原语转换(第 5.1.2 节)适用于转换以下规则指定的一个或两个操作数:

如果任一操作数是 double 类型,则另一个将转换为 double

在您的示例中,您有一个 Integer 和一个 Double。它们被拆箱为intdouble,然后int 被转换为double

【讨论】:

    【解决方案2】:

    发生了一些奇怪的自动装箱操作 - 如果您使用不同的数字,您会看得更清楚:

        Object myObject = true ? new Integer(25) : new Double(22.0);
    

    现在,myObject 仍将被分配一个 Double(25.0),而不是如果条件不起作用时您期望的 22.0。基本上,因为 Java 认为您正在执行某种涉及 int 和 double 的计算,所以它会将 iif 的结果作为“double”原语返回,然后将其自动装箱回 Double()。

    您还可以通过强制将值视为 Object() 类型来使其行为符合预期:

        Object myObject = true ? (Object) new Integer(25) : (Object) new Double(22.0);
    

    【讨论】:

      【解决方案3】:

      编译后

      Object myObject = true ? new Integer(25) : new Double(25.0);

      如下所示

      Object myObject = (double) new Integer(25);

      因此,它按预期返回 new Integer(25),但它被转换为 double。

      正如 Eran 提到的,根据JLS 5.6.2

      二进制数字提升(第 5.6.2 节)应用于操作数类型,并且 条件表达式的类型是提升的类型 第二和第三个操作数。

      1. 如果任何操作数属于引用类型,则将对其进行拆箱转换(第 5.1.8 节)。
      2. 加宽原语转换(第 5.1.2 节)适用于转换以下规则中指定的一个或两个操作数:

        • 如果任一操作数为 double 类型,则另一个将转换为 double

        • 否则,如果任一操作数为浮点类型,则转换另一个 浮动。

        • 否则,如果任一操作数为 long 类型,则转换另一个 太长了。

        • 否则,两个操作数都转换为 int 类型。

      【讨论】:

        猜你喜欢
        • 2020-01-10
        • 2013-02-10
        • 1970-01-01
        • 2013-07-08
        • 1970-01-01
        • 2020-10-29
        • 1970-01-01
        • 2011-08-19
        • 2015-09-14
        相关资源
        最近更新 更多