Причины довольно сложны, но все они в деталях ( мелкий шрифт, если хотите) Спецификации языка 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. Вы можете использовать расширенное ссылочное преобразование, только если исходный тип является подтипом целевого типа.