由三元运算符产生的意外类型

时间:2014-08-10 15:37:05

标签: java ternary-operator

我正在尝试编写一个获取double的方法,验证该数字是否在点之后有什么内容,如果确实有 - 返回double,如果没有则返回{ {1}}。

int

输出:

public class Solution {
    public static void main(String[] args) {
        double d = 3.000000000;
        System.out.println(convert1(d));
        System.out.println(convert2(d));
    }

    static Object convert1(double d) {
        if(d % 1 == 0)
            return (int) d;
        else
            return d;
    }

    static Object convert2(double d) {
        return ((d%1) == 0) ? ((int) (d)) : d;
    }
}

因此,我想要的一切都发生在方法3 3.0 中,但不会发生在方法convert1()中。看来这些方法必须做同样的工作。但我做错了什么?

4 个答案:

答案 0 :(得分:25)

您会看到与the one in this question类似的效果。

使用三元运算符处理Java的方式与使用if语句处理类型的方式略有不同。

具体来说,standard says

  

条件表达式的类型确定如下:

     

...

     

否则,如果第二个和第三个操作数具有类型   convertible(§5.1.8)到数字类型,然后有几种情况:

     

...

     

否则,二进制数字促销(第5.6.2节)将应用于   操作数类型和条件表达式的类型是   提升了第二和第三个操作数的类型。

翻到标准页面we see

  

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

这是在这里发生的事情,然后自动装箱到Double。似乎if语句没有发生这种转换,解释了差异。

更广泛地说 - 这不是一个好主意。根据价值,我不认为退回intdouble中的一个是好的设计 - 如果你要关闭某些东西,请使用Math.floor,如果你不赞成不希望打印小数,请使用printf

编辑:我认为做一些hacky事情来规避常规数字转换系统并不是一个好主意。这是一个直接为您提供String的想法,这似乎是您想要的:

static String convert3(double d) {
    return ((d % 1 == 0) ? Integer.toString((int)d) : Double.toString(d));
}

答案 1 :(得分:15)

正如其他答案所述,这种行为是因为三元表达式的两种可能结果必须具有相同的类型。

因此,为了使您的三元版本与convert1()的工作方式相同,您需要做的就是将int投射到Object

static Object convert2(double d) {
    return ((d % 1) == 0) ? ((Object) (int) (d)) : d;
}

答案 2 :(得分:11)

三元运算符要求两个结果值都是相同的类型,因此int会自动(安全)扩展到double

三元与if“等价物”不完全相同。

答案 3 :(得分:0)

解决点后的数字问题:

public Object convert(double number){
  double whole = Math.floor(number);
  if(Math.abs(whole - number) < DELTA){
    return (int) number;
  }
  return number;
}

DELTA是足够小的常量,用于解决浮点格式编码的整数问题。

我已经从内存中编写了代码,但我认为其背后的想法很明确。