С Java 7 система литья должна была слегка измениться в отношении примитивных типов, чтобы разрешить работу с MethodHandle
. При вызове дескриптора метода компилятор javac генерирует so-called polymorhic signature, который получается из сигнатур метода метода.Эти полиморфные сигнатуры создаются путем указания типа параметра с литьем. Например, при связывании метод с подписью double, long -> int
, требуется следующая литья:
Number foo = 42d, bar = 43L;
int ignored = (int) methodHandle.invoke((double) object, (long) bar);
Исходный код подписи MethodHandle::invoke
, однако, определяется как Object[] -> Object
, без непосредственного литья значение примитивного типа, полиморфная подпись не может быть сгенерирована.
Очевидно, что для того, чтобы это было возможно, компилятор Java должен был быть изменен, чтобы позволить такие отливки, которые ранее не были законными. Хотя теоретически было бы возможно ограничить это использование отливок методами, которые были аннотированы с помощью @PolymorhicSignature
, это привело бы к странному исключению, почему в настоящее время вообще возможно в javac, где соответствующий байт-код генерируется, когда не создается полиморфная подпись. Тем не менее, примитивные типы до сих пор представляют свои собственные типы времени выполнения, что было указано в другой ответ, который разместил сгенерированного байт-код такого литья за пределами MethodHandle
Object foo = 42;
int.class.cast(foo);
приведет к исключению во время выполнения.
Однако я согласен с комментариями, что это не обязательно должно быть должным образом рассмотрено в JLS, но я found a thread mentioning this specification gap. Упоминается, что спецификация должна быть обновлена соответствующим образом после того, как появятся лямбда-выражения, но JLS для Java 8, похоже, не упоминает такие отливки или @PolymorphicSignature
. В то же время в нем указывается, что [a] ny конверсия, которая явно не разрешена, запрещена.
Возможно, JLS в настоящее время отстает от реализации javac javac, и компилятор Eclipse, конечно же, не выбрал это правильно. Вы можете сравнить это с некоторыми corner-cases of generic type inference, где несколько IDE-компиляторов ведут себя по-другому, что javac до сегодняшнего дня.
Это не то, что позволяет JLS. –
@PeterLawrey: Я тоже этого не ожидал, но javac 1.7 на Linux, похоже, разрешает это. Интересно. –
Он должен работать, если вы сделаете это 'double nr = n == null? 0.0: (Double) n; ' –