Java转换:是编译器错了,还是语言规范错了,还是我错了?
我一直在阅读Java语言规范,第3版,并发现我认为规范和javac编译器实现之间存在差异。Eclipse 编译器中也存在同样的差异。
第 15.16 节讨论了强制转换表达式。它说,如果参数类型无法通过强制转换转换为强制转换类型,则应该是编译时错误(第5.5节):
如果根据强制转换转换规则 (§5.5) 永远不能将操作数的编译时类型强制转换为强制转换运算符指定的类型,则这是一个编译时错误。否则,在运行时,通过强制转换转换为强制转换运算符指定的类型,操作数值将转换(如有必要)。
第5.5节讨论了铸造转换。它提供了允许的转换类型的列表。列表中特别缺少的是“拆箱转换,然后加宽/缩小基元转换”。然而,javac编译器(以及Eclipse编译器)似乎确实允许这种确切的转换顺序。例如:
long l = (long) Integer.valueOf(45);
...编译刚刚好。(有问题的强制转换是强制转换为;参数的类型为 ,因此转换需要取消装箱,然后进行加宽的基元转换)。long
java.lang.Integer
int
同样,根据 JLS,不应该从 强制转换为 ,因为这(根据 5.1.4)需要加宽基元转换和缩小基元转换 - 但是,编译器也允许这种强制转换。byte
char
任何人都可以启发我吗?
编辑:自从问这个问题以来,我已经向Oracle提交了错误报告。他们的回答是,这是“JLS中的一个小故障”。