Ne compile pas:
void test(Integer x) {
switch (x) {
case 'a':
}
}
Compile OK:
void test(Byte x) {
switch(x) {
case 'a':
}
}
java
java-8
switch-statement
ali gh
la source
la source
'a'
cas sera exécuté dans le cas quix
est l'octet97
. (Essayez-le si vous ne me croyez pas.) Pour la vraie explication, voir ma réponse.Réponses:
Les raisons sont assez compliquées, mais elles se trouvent toutes dans les détails (en petits caractères si vous le souhaitez) de la spécification du langage Java.
Tout d'abord, le JLS 14.11 dit ce qui suit au sujet des
switch
déclarations:Cela signifie que
'a'
doit être attribuable àInteger
etByte
respectivement.Mais cela ne semble pas juste:
On pourrait penser que puisque
'a'
devrait être attribuable à une affectationInteger
carchar
->int
est légale. (Toutechar
valeur rentrera dans unint
.)Vous penseriez que puisque
'a'
ne devrait PAS être attribuable à une affectationByte
parce quechar
->byte
n'est PAS légal. (La plupart deschar
valeurs ne rentrent pas dans un octet.)En fait, ni l'un ni l'autre n'est correct. Pour comprendre pourquoi, nous devons lire ce que JLS 5.2 fait réellement sur ce qui est autorisé dans les contextes d'affectation.
Pour passer de
'a'
àInteger
, il faudrait 1 élargir lachar
valeur à anint
puis encadrer laint
à anInteger
. Mais si vous regardez les combinaisons de conversions autorisées, vous ne pouvez pas faire une conversion primitive élargie suivie d'une conversion de boxe.Par conséquent ,
'a'
àInteger
n'est pas autorisé. Cela explique l'erreur de compilation dans le premier cas.On pourrait penser que
'a'
toByte
est interdit car cela impliquerait une conversion de rétrécissement primitive ... qui n'est pas du tout dans la liste. En fait, les littéraux sont un cas particulier. JLS 5.2 poursuit en disant ce qui suit.La seconde s'applique
'a'
àByte
, car:'a'
est97
décimale, qui se situe dans la plage debyte
(-128
à+127
).Cela explique pourquoi il n'y a pas d'erreur de compilation dans le deuxième exemple.
1 - Nous ne pouvons pas boxer
'a'
vers aCharacter
puis élargirCharacter
versInteger
car ilCharacter
ne s'agit pas d'un sous-type Java deInteger
. Vous ne pouvez utiliser une conversion de référence élargie que si le type source est un sous-type du type cible.la source
int
comme type de commutateur? (depuischar -> int
l'élargissement primitif qui est autorisé)