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.
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):
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.
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);
... 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).
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?
Edit: since asking this, I have filed a bug report with Oracle. Their response is that this is a "glitch in the JLS".
long l = (long) Integer.valueOf(45);
– Br