Я читал спецификацию языка Java, 3-е издание, и обнаружил, как мне кажется, несоответствие между спецификацией и реализацией компилятора javac. Такие же расхождения существуют в компиляторе Eclipse.
Раздел 15.16 говорит о приведенных выражениях. В нем говорится, что это должно быть ошибкой времени компиляции, если тип аргумента не может быть преобразован в тип преобразования посредством преобразования преобразования (раздел 5.5):
Ошибка времени компиляции, если тип операнда во время компиляции никогда не может быть приведен к типу, указанному оператором приведения в соответствии с правилами преобразования приведения (§5.5). В противном случае во время выполнения значение операнда преобразуется (при необходимости) путем преобразования преобразования к типу, указанному оператором преобразования.
Раздел 5.5 говорит о конвертации каста. Это дает список типов конверсии, которые разрешены. Конкретно отсутствует в списке «преобразование без коробки с последующим расширением / сужением преобразования примитивов». Однако эта точная последовательность преобразований, по-видимому, разрешена компилятором javac (а также компилятором Eclipse). Например:
long l = (long) Integer.valueOf(45);
... компилируется просто отлично. (Проблематичным является приведение к long
; аргумент имеет тип java.lang.Integer
, поэтому преобразование требует распаковки в int
с последующим расширением примитивного преобразования).
Аналогично, согласно JLS не должно быть возможности приводить от byte
до char
, потому что это (согласно 5.1.4 ) требует расширяющегося примитивного преобразования и сужающее примитивное преобразование - однако, это приведение также разрешено компиляторами.
Может кто-нибудь просветить меня?
Редактировать: с тех пор, как я спросил об этом, я подал отчет об ошибке в Oracle. Их ответ заключается в том, что это «сбой в JLS».