在Java1.8.0_152中使用Math.round(双d)时强制转换为int

在Java1.8.0_152中使用Math.round(双d)时强制转换为int,java,math,casting,java-8,rounding,Java,Math,Casting,Java 8,Rounding,我不明白为什么代码段1工作正常,但代码段2给出了编译时错误不兼容类型:java.lang.Long无法转换为int 与java中强制转换的优先级有关吗?我经历了这一切,但毫无帮助 请详细解释在这两个代码段的幕后发生了什么,以及为什么它没有在代码段1中给出错误 代码片段1: package com.company; public class Main { public static void main(String[] args) { double dbl = 1

我不明白为什么代码段1工作正常,但代码段2给出了编译时错误
不兼容类型:java.lang.Long无法转换为int

与java中强制转换的优先级有关吗?我经历了这一切,但毫无帮助

请详细解释在这两个代码段的幕后发生了什么,以及为什么它没有在代码段1中给出错误

代码片段1:

package com.company;

public class Main
{
    public static void main(String[] args)
    {
        double dbl = 10.25;
        int i1 = (int)Math.round(dbl);
    }
}
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;
    }
}
代码片段2:

package com.company;

public class Main
{
    public static void main(String[] args)
    {
        double dbl = 10.25;
        int i1 = (int)Math.round(dbl);
    }
}
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中:

double dbl = 10.25;
int i1 = (int) Math.round(dbl);
您声明了一个
double
。四舍五入后的结果是
长的
。然后是对
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
或者,如果您有Java8,使用
Math#toIntExact
(),如果
long
不适合
int
,它将抛出
算术异常:

int i2 = Math.toIntExact(lng.longValue());
请注意,Java不会自动将
Long
取消装箱到
Long
,然后将其强制转换为
int
,您需要自行明确取消装箱,如图所示


这只是JVM强制转换规则之一,在本例中可能是为了防止无意的编程错误

int
long
double
是原语,它们可以被强制转换<代码>整数
是对象,不可能强制转换。请检查列出强制转换原语规则的列表。看起来
long
int
是一个允许的变窄演员阵容。@Zabuza你让我很开心。现在我明白了问题所在。因此,如果在snippet#1中使用
long
,而不是
long
,它就会起作用。天哪四舍五入后的结果不是两倍。实际上,它返回
long
。当然,请参考@AnV-Oh。谢谢,更正。@Holger是的,由于有损转换。编辑了答案,谢谢。