我一直在阅读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中的一个小故障".
我认为你是对的,编译器是对的,规范是错误的......
\n\n这可以编译:(Object)45而这不能:(Long)45
理解编译器行为(包括我正在使用的 Intellij)的唯一方法是修改强制转换以与赋值转换和方法调用转换一致:
\n\n装箱转换 (\xc2\xa75.1.7)\n后面可以选择加宽\n引用转换
拆箱转换 (\xc2\xa75.1.8)\n可选地后跟\n扩大原始转换。
加
\n\n该规范确实说“强制转换比赋值或方法调用转换更具包容性:强制转换可以执行除字符串转换或捕获转换之外的任何允许的转换”
\n| 归档时间: |
|
| 查看次数: |
906 次 |
| 最近记录: |