Os motivos são bastante complicados, mas estão todos nos detalhes ( letras pequenas, se você preferir ) da Especificação de Linguagem Java.
Primeiro, o JLS 14.11 diz o seguinte sobre switch
declarações:
"Toda constante de caso associada à instrução switch deve ser atribuída compatível com o tipo de expressão da instrução switch ( §5.2 )."
Isso significa que 'a'
precisa ser atribuível Integer
e Byte
respectivamente.
Mas isso não parece certo:
Você pensaria que desde que 'a'
deve ser atribuível a uma Integer
porque char
-> int
atribuição é legal. (Qualquer char
valor caberá em um int
.)
Você pensaria que uma vez 'a'
que NÃO deve ser atribuível a uma Byte
porque char
-> a byte
atribuição NÃO é legal. (A maioria dos char
valores não cabe em um byte.)
De fato, nenhuma delas está correta. Para entender o porquê, precisamos ler o JLS 5.2 sobre o que é permitido nos contextos de atribuição.
"Os contextos de atribuição permitem o uso de um dos seguintes :
- uma conversão de identidade (§5.1.1)
- uma conversão primitiva alargada (§5.1.2)
- uma conversão de referência ampliada (§5.1.5)
- uma conversão de referência ampliada seguida por uma conversão de unboxing
- uma conversão de referência de ampliação seguida por uma conversão de unboxing e, em seguida, uma conversão primitiva de ampliação
- uma conversão de boxe (§5.1.7)
- uma conversão de boxe seguida por uma conversão de referência ampliada
- uma conversão de unboxing (§5.1.8)
- uma conversão de unboxing seguida por uma conversão primitiva de ampliação ".
Para passar de 'a'
para Integer
, precisaríamos 1 ampliar o char
valor para uma int
caixa e depois a int
para um Integer
. Mas se você observar as combinações de conversões permitidas, não poderá fazer uma conversão primitiva de ampliação seguida por uma conversão de boxe.
Portanto 'a'
a Integer
não é permitido. Isso explica o erro de compilação no primeiro caso.
Você poderia pensar que 'a'
a Byte
não é permitido porque isso envolveria uma conversão de restrição primitiva ... que não está na lista de todo. De fato, literais são um caso especial. O JLS 5.2 continua dizendo o seguinte.
"Além disso, se a expressão for uma expressão constante ( §15.28 ) do tipo byte, short, char ou int:
Uma conversão primitiva de restrição pode ser usada se a variável for do tipo byte, curta ou char, e o valor da expressão constante for representável no tipo da variável.
Uma conversão primitivo estreitando seguido por uma conversão boxe pode ser usado se a variável é do tipo Byte
, Short
ou Character
, e o valor da expressão constante é representável no tipo byte, curto, ou carvão animal, respectivamente ".
O segundo deles se aplica 'a'
a Byte
, porque:
- um literal de caractere é uma expressão constante e
- o valor de
'a'
é 97
decimal, que está dentro do intervalo de byte
( -128
para +127
).
Isso explica por que não há erro de compilação no segundo exemplo.
1 - Não pode caixa 'a'
a um Character
e depois ampliar Character
para Integer
porque Character
não é um subtipo Java Integer
. Você só pode usar uma conversão de referência ampliada se o tipo de origem for um subtipo do tipo de destino.