Java转换:是编译器错误,还是语言规范错误,或者我错了? [英] Java casting: is the compiler wrong, or is the language spec wrong, or am I wrong?

查看:154
本文介绍了Java转换:是编译器错误,还是语言规范错误,或者我错了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读Java语言规范第3版,并且发现了我认为规范和javac编译器实现之间的差异。 Eclipse编译器中存在相同的差异。

I have been reading the Java Language Spec, 3rd edition, and have found what I think is a discrepancy between the spec and the javac compiler implementation. The same discrepancies exist in the Eclipse compiler.

部分 15.16 讨论了强制转换表达式。如果参数类型无法通过强制转换转换为强制类型,那么它应该是编译时错误(第5.5节):

Section 15.16 talks about cast expressions. It says that it should be a compile time error if the argument type cannot be converted to the cast type via casting conversion (section 5.5):


如果根据转换转换规则(第5.5节),操作数的编译时类型永远不会转换为强制转换运算符指定的类型,那么这是一个编译时错误。否则,在运行时,通过将转换转换为强制转换运算符指定的类型来转换操作数值(如有必要)。

It is a compile-time error if the compile-time type of the operand may never be cast to the type specified by the cast operator according to the rules of casting conversion (§5.5). Otherwise, at run-time, the operand value is converted (if necessary) by casting conversion to the type specified by the cast operator.

5.5 部分讨论了转换。它给出了允许的转换类型列表。列表中特别缺少的是取消装箱转换,然后加宽/缩小原始转换。 但是 javac编译器(以及Eclipse编译器)似乎确实允许确切的转换序列。例如:

Section 5.5 talks about casting conversion. It gives a list of conversion types which are allowed. Specifically absent from the list is "unboxing conversion followed by widening/narrowing primitive conversion". However that exact sequence of conversions does seem to be allowed by the javac compiler (and also the Eclipse compiler). For instance:

long l = (long) Integer.valueOf(45);

...编译得很好。 (有问题的强制转换是强制转换为 long ;参数类型为 java.lang.Integer ,因此转换需要拆箱到 int 然后加宽原始转换。)

... compiles just fine. (The problematic cast is the cast to long; the argument is of type java.lang.Integer, so the conversion requires unboxing to int followed by a widening primitive conversion).

同样,根据JLS,它不应该是可以从 byte 转换为 char ,因为那(根据 5.1.4 )需要扩展原始转换 a缩小原始转换 - 但是,编译器也允许这种强制转换。

Likewise, according to the JLS it should not be possible to cast from byte to char, because that (according to 5.1.4) requires a widening primitive conversion and a narrowing primitive conversion - however, this cast is also allowed by the compilers.

任何人都可以启发我吗?

Can anyone enlighten me?

编辑:自提出此问题以来,我已提交错误报告与Oracle合作。他们的回答是,这是JLS中的小故障。

since asking this, I have filed a bug report with Oracle. Their response is that this is a "glitch in the JLS".

推荐答案

我认为你是对的,编译器是对的,并且规范是错误的....

I think you are right, the compilers are right, and the spec is wrong....

这个编译:(对象)45 而这不是:(长)45

This compiles: (Object)45 and this does not: (Long)45

了解编译器行为的唯一方法(包括我正在使用的Intellij)是否修改了转换转换以同意分配转换和方法调用转换:

The only way to make sense of the compilers' behavior (including Intellij I'm using) is if Casting Conversion is modified to agree with Assignment Conversion and Method Invocation Conversion:


  • 装箱转换(第5.1.7节)
    之后可选择加宽
    参考转换

  • a boxing conversion (§5.1.7) optionally followed by widening reference conversion

拆箱转换(§5.1.8)
可选地后跟加宽
原始转换。

an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

加上


  • 扩大和缩小原始转换

规范确实说转换转换比赋值或方法调用更具包容性转换:演员阵容可以做到允许转换而不是字符串转换或捕获转换

The spec did say "casting conversions are more inclusive than assignment or method invocation conversions: a cast can do any permitted conversion other than a string conversion or a capture conversion"

这篇关于Java转换:是编译器错误,还是语言规范错误,或者我错了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆