Причини досить складні, але вони все в деталях ( дрібний шрифт , якщо ви хочете) з специфікації мови Java.
По-перше, JLS 14.11 говорить про наступні 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 ) типу байта, шрифту, знака або int:
Примітивне перетворення, що звужує, може бути використане, якщо змінна має тип байта, короткого чи знаку, а значення постійного вираження є представним у типі змінної.
Примітивне перетворення, що супроводжується звуженням, за яким слід перетворення боксу, може бути використане, якщо змінна має тип Byte, Shortабо Character, і значення постійного вираження є представним відповідно в байті типу, короткому або знаку відповідно. "
Другий з них відноситься до 'a'до Byte, тому що:
- буквений символ - це постійний вираз, і
- величина
'a'є 97десяткової, який знаходиться в межах діапазону byte( -128з +127).
Це пояснює, чому немає помилки компіляції у другому прикладі.
1 - Ми не можемо боксувати 'a'до , Characterа потім розширити Characterдо , Integerтому що Characterце не Java підтип Integer. Можна використовувати розширювальну перехідну посилання лише тоді, коли тип джерела є підтипом цільового типу.