Не компилируется:
void test(Integer x) {
switch (x) {
case 'a':
}
}
Компилирует ОК:
void test(Byte x) {
switch(x) {
case 'a':
}
}
java
java-8
switch-statement
али гх
источник
источник
'a'
случае будет выполнен в случае, которыйx
является байтом97
. (Попробуйте, если вы мне не верите.) Для реального объяснения смотрите мой ответ.Ответы:
Причины довольно сложны, но все они в деталях ( мелкий шрифт, если хотите) Спецификации языка Java.
Прежде всего, JLS 14.11 говорит следующее об
switch
утверждениях:Это означает, что
'a'
должно быть назначеноInteger
иByte
соответственно.Но это не звучит правильно:
Можно было бы подумать , что так
'a'
должно быть отнесено кInteger
потому , чтоchar
->int
назначение является законным. (Любоеchar
значение будет соответствоватьint
.)Можно было бы подумать , что , поскольку
'a'
не должно быть назначаемыми наByte
потому , чтоchar
->byte
назначение не является законным. (Большинствоchar
значений не помещаются в байт.)На самом деле, ни то, ни другое не является правильным. Чтобы понять почему, нам нужно прочитать, что на самом деле JLS 5.2 о том, что разрешено в контекстах присваивания.
Чтобы перейти от
'a'
кInteger
, мы должны были бы 1 расширитьchar
значение наint
то ЯЩИКint
АньInteger
. Но если вы посмотрите на комбинации разрешенных преобразований, вы не сможете выполнить расширенное преобразование примитивов с последующим преобразованием в бокс.Поэтому ,
'a'
чтобыInteger
не допускается. Это объясняет ошибку компиляции в первом случае.Можно подумать, что
'a'
кByte
отвергается , потому что повлечет за собой примитивное сужающее преобразование ... , который не находится в списке вообще. На самом деле, литералы - это особый случай. JLS 5.2 продолжает говорить следующее.Второй из них относится
'a'
кByte
, потому что:'a'
является97
десятичным, которое находится в пределах диапазона отbyte
(-128
до+127
).Это объясняет, почему нет ошибки компиляции во втором примере.
1 - Мы не можем боксировать
'a'
к ,Character
а затем расширитьCharacter
до ,Integer
потому чтоCharacter
это не Java подтипInteger
. Вы можете использовать расширенное ссылочное преобразование, только если исходный тип является подтипом целевого типа.источник
int
в качестве типа переключателя? (посколькуchar -> int
допускается примитивное расширение)