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