Причины довольно сложны, но все они в деталях ( мелкий шрифт, если хотите) Спецификации языка 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)
- распаковка конверсии с последующим расширением примитивного преобразования. "
Чтобы перейти от '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
).
Это объясняет, почему нет ошибки компиляции во втором примере.
1 - Мы не можем боксировать 'a'
к , Character
а затем расширить Character
до , Integer
потому что Character
это не Java подтип Integer
. Вы можете использовать расширенное ссылочное преобразование, только если исходный тип является подтипом целевого типа.