我一直在阅读Java语言规范第3版,并且发现了我认为规范和javac编译器实现之间的差异.Eclipse编译器中存在相同的差异.
第15.16节讨论了强制转换表达式.如果参数类型无法通过强制转换转换为强制类型,那么它应该是编译时错误(第5.5节):
如果根据转换转换规则(第5.5节),操作数的编译时类型永远不会转换为强制转换运算符指定的类型,那么这是一个编译时错误.否则,在运行时,通过将转换转换为强制转换运算符指定的类型来转换操作数值(如果需要).
第5.5节讨论了转换.它给出了允许的转换类型列表.列表中特别缺少的是"取消装箱转换,然后加宽/缩小原始转换".但是,javac编译器(以及Eclipse编译器)似乎确实允许确切的转换序列.例如:
long l = (long) Integer.valueOf(45);
Run Code Online (Sandbox Code Playgroud)
......编译得很好.(有问题的强制转换是强制转换long;参数是类型java.lang.Integer,因此转换需要拆箱int后跟扩展的原始转换).
同样地,根据JLS它不应该是可以从铸造byte到char,因为(根据5.1.4)需要加宽原语转换和一个基本收缩转换-然而,该铸造也由编译器允许的.
任何人都可以开导我吗?
编辑:自从问这个以来,我已经向Oracle 提交了一份错误报告.他们的反应是,这是"JLS中的一个小故障".
final byte b = 12;
Short s = b;
Integer i = b;
Run Code Online (Sandbox Code Playgroud)
程序编译为Short,但是对于Integer编译失败,出现"不兼容类型"消息.
我很难理解这种行为.我找不到任何针对这种特定情况的东西..