With Java 7, the casting system had to be changed slightly with regards to primitive types in order to allow working with MethodHandle
s. When invoking a method handle, the javac compiler generates a so-called polymorhic signature which derives from the method handle's method signatures. These polymorphic signatures are created by hinting out a parameter's type with a casting. For example, when binding a method with a signature of double, long -> int
, the following casting is required:
Number foo = 42d, bar = 43L;
int ignored = (int) methodHandle.invoke((double) object, (long) bar);
The source code signature of MethodHandle::invoke
is however defined as Object[] -> Object
, without directly casting a value to a primitive type, the polymorphic signature could not be generated.
Obviously, for this to be possible, the Java compiler had to be changed to allow such castings which were not previously legal. While it would - in theory - be possible to restrict this use of castings to methods that are annotated with @PolymorhicSignature
, this would have resulted in a strange exception why it is now generally possible in javac where appropriate byte code is generated when not creating a polymorphic signature. Yet, primitive types still represent their own runtime types what was pointed out in the other answer that posted the generated byte code of such a casting outside of a MethodHandle
Object foo = 42;
int.class.cast(foo);
would result in a runtime exception.
However, I agree with the comments that this is not necessarily dicussed appropriately in the JLS but I found a thread mentioning this specification gap. It is mentioned that the specification should be updated accordingly once lambda expressions are put in place but the JLS for Java 8 does not seem to mention such castings or @PolymorphicSignature
either. At the same time, it states that [a]ny conversion that is not explicitly allowed is forbidden.
Arguably, the JLS is currently lagging behind the javac implementation and the Eclipse compiler has surely not picked this up properly. You could compare this to some corner-cases of generic type inference where several IDE compiler behave differently that javac until today.
double nr = n == null ? 0.0 : (Double) n;
– GibraltardoubleValue()
because that one also works if the actual class isInteger
(the value comes from some library, and it could be next release returns Integer instead of Double for integral values). – SagittariusNumber
allows for automaticunboxing
. Your example is valid but its not recommended - you should stick todoubleValue
and the likes. Note that unboxing can only happen for/tointegral primitives
in the case ofNumber
– ElapseNumber
doesn't support implicit unboxing. – GibraltarConverting an object of a wrapper type (Integer) to its corresponding primitive (int) value is called unboxing
Number
has no corresponding primitive type. – GibraltarNumber
todouble
should not be possible. – SagittariusDouble
may be unboxed todouble
---Double
is aNumber
soNumber
itself may also be unboxed independently but precision-losses may occur since the exact implementation ofNumber
is not known without additional effort. I think you should stop digging through JLS and start digging through actual sourcecode, a lot of things are easy to understand all of sudden once you look at reality instead of theory. – Elapse