Причини досить складні, але вони все в деталях ( дрібний шрифт , якщо ви хочете) з специфікації мови 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
. Можна використовувати розширювальну перехідну посилання лише тоді, коли тип джерела є підтипом цільового типу.