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

Lys*_*rii 19 java ternary-operator

我正在尝试编写一个获取a的方法double,验证数字是否在点之后有一些东西,如果它确实 - 返回一个double,如果没有 - 返回一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

3
3.0
Run Code Online (Sandbox Code Playgroud)

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

Pat*_*ins 25

你会看到类似于这个问题的效果.

稍微不同的规则控制Java使用三元运算符处理类型的方式而不是if语句.

具体来说,标准说:

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

...

否则,如果第二个和第三个操作数具有可转换(第5.1.8节)到数字类型的类型,则有几种情况:

...

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

翻到标准页面,我们看到:

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

这是在这里发生的事情,然后自动装箱到一个Double.似乎该if声明没有发生这种转换,解释了这种差异.

更广泛地说 - 这不是一个好主意.我不认为返回一个int或一个double取决于值的好设计- 如果你想要关闭一些东西,使用Math.floor,如果你不想打印小数,请使用printf.

编辑:我不认为做一些hacky事情绕过常规的数字转换系统是个好主意.这是一个String直接给你一个想法,这似乎是你想要的:

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


Kep*_*pil 15

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

因此,您需要做的就是使您的三元版本的工作方式convert1()与将其int转换为Object:

static Object convert2(double d) {
    return ((d % 1) == 0) ? ((Object) (int) (d)) : d;
}
Run Code Online (Sandbox Code Playgroud)

  • 你可以做得稍微好一点,然后施放给`Number`,对吗? (6认同)

Boh*_*ian 11

三元运算符要求两个结果值都是相同的类型,因此需要int进行自动(安全)加宽double.

三元与其if"等价" 并不完全相同.