我不明白为什么代码段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;
}
}
答案 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#toIntExact
(documentation),如果ArithmeticException
不适合,则会long
进入int
:
int i2 = Math.toIntExact(lng.longValue());
请注意,Java不会将您的Long
重新打包到long
,然后自动将其转换为int
,您需要自行显示取消装箱,如图所示。< / p>
它只是 JVM 的强制转换规则之一,在这种情况下可能是为了防止无意的编程错误。