【问题标题】:Java - ternary operator weird behaviourJava - 三元运算符奇怪的行为
【发布时间】:2016-07-14 17:06:44
【问题描述】:

我试图从double 中删除fractional 部分,以防它是整个使用:

(d % 1) == 0 ? d.intValue() : d

遇到了以下我不理解的行为:

public static void main(String[] args) {
    Double d = 5D;
    System.out.println((d % 1) == 0);                               // true
    System.out.println((d % 1) == 0 ? d.intValue() : "not whole");  // 5
    System.out.println((d % 1) == 0 ? d.intValue() : d);            // 5.0
}

正如您在第三行中看到的那样,即使满足 (d % 1) == 0 条件,操作员也会选择 else 值 - 5.0

这是怎么回事?

【问题讨论】:

  • 在这两种情况下都选择d.intValue(),它只是执行转换以确保第二个和第三个参数具有相同的类型。
  • 可能被视为 stackoverflow.com/questions/8002603/… 的副本(及其所有副本)...
  • @Marco13,我在发布问题时不知道投射是问题。事后看来,这可能是重复的..
  • 您正在尝试从double 中删除小数部分

标签: java double ternary-operator


【解决方案1】:

三元条件运算符的返回类型必须是第二个和第三个操作数都可以分配给它。

因此,在第二种情况下,运算符的返回类型是Object(因为d.intValue()"not whole" 必须都可以分配给它)而在第三种情况下它是Double(因为@ 987654325@ 和 d 必须可以分配给它)。

打印运行时类型为IntegerObject 会得到5,而打印Double 会得到5.0

【讨论】:

  • 但是当两者都可以分配给String时,为什么它被转换为Object而不是String
  • @Daniel 实际上,Integer 不能分配给String,它必须先转换为字符串(例如,通过使用IntegertoString)。它仅在您的示例中转换为字符串以便由 println 打印。
【解决方案2】:

表达式a ? b : c 的类型始终与cbc 最接近的公共父级相同。

System.out.println((d % 1) == 0 ? d.intValue() : "not whole");  // Comparable a parent of Integer and String
System.out.println((d % 1) == 0 ? d.intValue() : d);            // Double is a widened int

顺便说一句,d % 1 只会检查它是否是一个整体,而不是它足够小以适合int 值。更安全的检查是查看转换为 intlong 时的值是否相同

double d = 5.0;
if ((long) d == d)
    System.out.println((long) d);
else
    System.out.println(d);

或者你可以防止它扩大long 回到双倍

double d = 5.0;
System.out.println((long) d == d ? Long.toString((long) d) : Double.toString(d));

【讨论】:

  • 谢谢,在我的情况下(数字代表 csat),最大可能值为 5,所以幸运的是,生活比这更简单..
【解决方案3】:

它选择正确。然后将其包裹成双倍。这是三个关键点:

  1. 如果第二个和第三个操作数的类型相同,那就是条件表达式的类型。换句话说,您可以避免使用混合类型的计算来避免整个混乱。

  2. 如果其中一个操作数是 T 类型,其中 T 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式,其值可在 T 类型中表示,则条件表达式的类型为T.

  3. 否则,二进制数值提升应用于操作数类型,条件表达式的类型为第二个和第三个操作数的提升类型。

【讨论】:

    【解决方案4】:

    在您的情况下,三元运算符的第二个和第三个参数是类型“int”和“Double”。 Java 必须将这些值转换为相同的类型,以便它们可以从三元运算符返回。 Java 语言规范中给出了执行此操作的规则。 https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25

    在您的情况下,这些规则导致两个参数都转换为“double”类型(“Double”是未装箱的,int 是值转换的)。

    解决方法是将参数强制转换为三元运算符,使它们属于同一类型(下面的括号可能比严格需要的多,我对 java 运算符优先级规则有点生疏)。

    System.out.println((d % 1) == 0 ? ((Number)(d.intValue())) : (Number)d); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      相关资源
      最近更新 更多