строку - Почему в Java 8 при переключении через оболочку Integer регистр 'char' не компилируется, но компиляция в порядке, когда коммутатор находится над байтом?



сравнение символов в строке java (1)

Причины довольно сложны, но все они в деталях ( мелкий шрифт, если хотите) Спецификации языка Java.

Прежде всего, JLS 14.11 говорит следующее о выражениях switch :

«Каждая константа регистра, связанная с оператором switch, должна быть совместима по присваиванию с типом выражения оператора switch ( §5.2 )».

Это означает, что 'a' должен быть назначен на Integer и Byte соответственно.

Но это не звучит правильно:

  • Вы могли бы подумать, что, поскольку 'a' должно быть присваиваемо 'a' числу, потому что присваивание char -> int допустимо. (Любое значение char будет вписываться в int .)

  • Вы могли бы подумать, что, поскольку 'a' НЕ должно быть назначено byte потому что присвоение byte char -> НЕ допустимо. (Большинство значений char не помещаются в байт.)

На самом деле, ни то, ни другое не является правильным. Чтобы понять почему, нам нужно прочитать, что на самом деле §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 не разрешено, потому что это будет включать в себя примитивное сужающее преобразование ... которого вообще нет в списке. На самом деле, литералы - это особый случай. §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 - Мы не можем добавить Character 'a' к Character а затем расширить Character до целого, потому что Character не является Java-подтипом целого Вы можете использовать расширенное ссылочное преобразование, только если исходный тип является подтипом целевого типа.

Не компилируется:

void test(Integer x){
      switch(x){
       case 'a':
      }
}

Компилирует ОК:

void test(Byte x){
      switch(x){
       case 'a':
      }
}




switch-statement