eclipse在Java7中允许从数字转换为双精度?(自动装箱)
一位同事签入此代码:
Number n = ...;
double nr = n == null ? 0.0 : (double) n;
另一位同事随后抱怨说,这没有编译,这正是我所期望的。然而,事实证明,我已经从SVN中提取了这段代码,并且一切正常。在eclipse中,我们都将Java版本设置为1.7,结果证明,在Eclipse4.4.2(Luna)下,代码可以很好地编译,但在4.2.2下失败
我用n.doubleValue()
替换了cast,解决了这个问题
现在真正的问题是:为什么这一点首先被接受?当然,它应该在向Double
而不是double
施放时起作用,但我认为直接从Number
施放到double
是不允许的。那么,这是Eclipse4.2.2中同时修复的一个bug,还是Eclipse4.4.2默默地接受不应该编译的代码(哪一个是bug)
# 1 楼答案
抽象类编号是BigDecimal、BigInteger、Byte、Double、Float、Integer、Long和Short类的超类
Double是Double的包装类,支持自动装箱,但不支持数字。换句话说,Number可以包含许多不是双精度的包装器类,所以需要显式转换。 请尝试以下代码:
# 2 楼答案
在Java7中,为了允许使用^{} s,强制转换系统必须在原语类型方面稍微改变。调用方法句柄时,javac编译器会生成一个so-called polymorhic signature,它来自方法句柄的方法签名。这些多态性签名是通过使用强制转换提示参数的类型来创建的。例如,当绑定签名为
double, long -> int
的方法时,需要进行以下转换:但是
MethodHandle::invoke
的源代码签名被定义为Object[] -> Object
,如果不直接将值转换为基元类型,则无法生成多态签名显然,为了实现这一点,必须对Java编译器进行更改,以允许以前不合法的铸造。虽然从理论上讲,可以将这种铸件的使用限制在用
@PolymorhicSignature
注释的方法上,但这会导致一个奇怪的例外,为什么现在在javac中,当不创建多态性签名时生成适当的字节码时,它现在通常是可能的。然而,原语类型仍然代表它们自己的运行时类型,这一点在另一个答案中指出,该答案将这种转换生成的字节码发布在MethodHandle
之外将导致运行时异常
然而,我同意以下评论,即这不一定在JLS中得到适当讨论,但我同意。有人提到,一旦lambda表达式就位,规范就应该相应地更新,但Java 8的JLS似乎没有提到此类铸件或
@PolymorphicSignature
。同时,声明禁止任何未明确允许的转换可以说,JLS目前落后于javac实现,Eclipse编译器肯定没有正确地处理这个问题。您可以将其与一些corner-cases of generic type inference进行比较,在这些corner-cases of generic type inference中,直到今天,几个IDE编译器的行为都不同于javac
# 3 楼答案
如注释中所述,数字没有相应的基元类型,但是Java编译器似乎很聪明,一旦你进行了转换,就可以在后台执行转换
下面是一个示例测试用例
包装试验
公共类编号rautoboxing{
}
我反编译了文件。类(我在windows上测试了jdk 7和8,结果是一样的),这就是结果
正如您所看到的,从数字到双精度的转换是以与取消装箱示例相同的方式进行的(从整数到整数)这是因为编译器将强制转换从
double
更改为Double
,从而允许取消装箱。似乎有两种交际方式(或者我在这一种上推测的类似方式)