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