Причины довольно сложные, но все они в деталях ( мелкий шрифт , если хотите) Спецификации языка Java.
Прежде всего, JLS 14.11 говорит следующее о switch
операторах:
"Каждая константа регистра, связанная с оператором switch, должна быть совместима с присваиванием с типом выражения выражения оператора switch ( §5.2 ). "
Это означает, что 'a'
необходимо назначить на Integer
и Byte
соответственно.
Но это не такправый звук:
Вы могли бы подумать , что, поскольку 'a'
должно быть , можно назначить Integer
, потому что char
-> int
присвоение законно. (Любое значение char
поместится в int
.)
Можно подумать , что, поскольку 'a'
НЕ должно быть присваивается Byte
, потому что char
-> byte
присваивание НЕ является законным. (Большинство char
значений не помещаются в байт.)
Фактически, ни одно из них не является правильным. Чтобы понять почему, нам нужно прочесть, что на самом деле JLS 5.2 о том, что разрешено в контекстах присваивания.
"Контексты присваивания позволяют использовать один изследующие :
- преобразование идентичности (§5.1.1)
- преобразование расширяющегося примитива (§5.1. 2)
- расширенное эталонное преобразование (§5.1.5)
- расширенное эталонное преобразование с последующим преобразованием распаковки
- преобразование с расширенным эталоном, за которым следует преобразование распаковки, а затем преобразование с расширением примитивов
- преобразование с использованием бокса (§5.1.7)
- преобразование в боксе с последующим расширением эталонного преобразования
- преобразование в распакованном виде (§5.1.8)
- anраспаковка конверсии с последующим расширением примитивного преобразования. "
Чтобы перейти от 'a'
к Integer
, мынам нужно 1 расширить значение char
до int
, а затем int
до Integer
. Но если вы посмотрите на комбинации разрешенных преобразований, вы не сможете выполнить расширенное преобразование примитивов с последующим преобразованием в бокс.
Следовательно, 'a'
в Integer
недопустимо. Это объясняет ошибку компиляции в первом случае.
Можно подумать, что от 'a'
до Byte
не разрешено, потому что это повлечет за собой примитивное сужающее преобразование ... которого вообще нет в списке. На самом деле, литералы - это особый случай. JLS 5.2 продолжает говорить следующее.
"Кроме того, если выражение является константным выражением ( §15.28 ) типаbyte, short, char или int:
Может использоваться сужающее примитивное преобразование, если переменная имеет тип byte, short или char, и значениеконстантного выражения представимо в типе переменной.
Может использоваться сужающее примитивное преобразование с последующим преобразованием в бокс, если переменная имеет тип Byte
, Short
или Character
, а значение константного выражения может быть представлено в типе byte, short или char соответственно. "
Второй из них относится к 'a'
к Byte
, потому что:
- символьный литерал является константным выражением, а
- значение
'a'
равно 97
десятичное число, которое находится в пределах диапазона от byte
(-128
до +127
).
Это объясняет, почему существует no ошибка компиляции во втором примере.
1 - Мы не можем поместить 'a'
в Character
и затем расширить Character
до Integer
, потому что Character
не подтип Java Integer
. Вы можете использовать расширенное ссылочное преобразование, только если исходный тип является подтипом целевого типа.