Я читал спецификацию языка 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».
long l = (long) Integer.valueOf(45);
- person Paŭlo Ebermann   schedule 22.03.2011