在Java 1.8.0_152中使用Math.round(double d)时转换为int

时间:2017-11-18 14:14:46

标签: java math casting java-8 rounding

我不明白为什么代码段1工作正常,但代码段2给出了编译时错误incompatible types: java.lang.Long cannot be converted to int

与java中的强制转换有关吗?我经历了这个thread on stackoverflow,但它并没有帮助。

请详细说明两个片段中幕后发生的情况以及它在代码片段1中没有出错的原因。

代码段1:

package com.company;

public class Main
{
    public static void main(String[] args)
    {
        double dbl = 10.25;
        int i1 = (int)Math.round(dbl);
    }
}

代码段2:

package com.company;

public class Main
{
    public static void main(String[] args)
    {
        double dbl = 10.25;
        Long lng = Math.round(dbl);
        int i2 = (int)lng;
    }
}

1 个答案:

答案 0 :(得分:1)

让我们仔细看看会发生什么。在代码段1

double dbl = 10.25;
int i1 = (int) Math.round(dbl);

您宣布double。四舍五入后的结果是long。然后是int的转换,这是可能的,因为两者都是原始类型,Java允许转换。然后将其存储在int

代码段2 中,但事情有所改变:

double dbl = 10.25;
Long lng = Math.round(dbl);
int i2 = (int) lng;

您声明double,round会返回long,但您希望将其存储在Long内。因此,Java会自动将long转换为Long,这称为自动装箱。 Java可以将所有原始类型包装到它们的包装类中。

最后你尝试将Long投射到int但这是不可能的,因为Long现在是一个对象。但是,它可以自动将Long取消设置为long。从那里你可以去int。我们先来看看这两个变种:

int i2 = (long) lng;           // Make unboxing explicit by casting
int i2 = lng.longValue()       // Use unboxing method

但由于以下原因,它无法编译:

  

不兼容的类型:从long到int的可能有损转换

所以转换是可能的,但编译器警告我们long可能不适合 int(有损转换),因此它阻止我们这样做

然而,我们可以通过强制转换显式进行转换:

int i2 = (int) lng.longValue() // The whole process completely explicit

或者,如果您有 Java 8 ,请使用Math#toIntExactdocumentation),如果ArithmeticException不适合,则会long进入int

int i2 = Math.toIntExact(lng.longValue());

请注意,Java不会将您的Long重新打包到long,然后自动将其转换为int,您需要自行显示取消装箱,如图所示。< / p>

它只是 JVM 强制转换规则之一,在这种情况下可能是为了防止无意的编程错误。