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

2022-09-01 21:53:59

我正在尝试编写一个方法,该方法获取一个,验证数字后面是否有东西,如果它有 - 返回一个,如果没有 - 返回一个。doubledoubleint

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()convert2()


答案 1

您看到的效果与本问题中的效果类似。

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

具体而言,该标准说

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

...

否则,如果第二个和第三个操作数具有可转换为数值类型的类型 (§5.1.8),则存在以下几种情况:

...

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

翻到标准的那个页面,我们看到

如果任一操作数的类型为双精度型,则另一个操作数将转换为双精度型。

这就是这里发生的事情,然后自动装箱到.该语句似乎没有发生此类转换,从而解释了差异。Doubleif

更广泛地说,---这不是一个好主意。我不认为根据值返回一个或一个是好的设计 - 如果你想舍入一些东西,请使用,如果你不想打印小数,请使用。intdoubleMath.floorprintf

编辑:我不认为做一些黑客的事情来规避常规的数字转换系统是一个好主意。这里有一个想法,可以直接给你一个,这似乎是你想要的:String

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

答案 2

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

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

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