46 votes

Pourquoi Java 12 essaie-t-il de convertir le résultat d'un switch en un nombre ?

Je suis d'accord que ce code :

var y = switch (0) {
    case 0 -> '0';
    case 1 -> 0.0F;
    case 2 -> 2L;
    case 3 -> true;
    default -> 4;
};
System.out.println(y);
System.out.println(((Object) y).getClass().getName());

renvoie ceci :

0
java.lang.Character

Mais si vous supprimez le booléen :

var y = switch (0) {
    case 0 -> '0';
    case 1 -> 0.0F;
    case 2 -> 2L;
    default -> 4;
};
System.out.println(y);
System.out.println(((Object) y).getClass().getName());

renvoie ceci :

48.0
java.lang.Float

Je suppose que ce résultat est inattendu.

0 votes

Probablement une sorte d'optimisation. Dans le second exemple, tous les résultats peuvent être convertis en flottants, alors que dans le premier exemple, il s'agit uniquement d'objets.

13 votes

J'imagine que c'est pour la même raison que true ? '0' : false retournerait un caractère parce qu'il nécessite nécessairement une mise en boîte, alors que true ? '0' : 0.0f renverrait un float car une promotion numérique binaire se produirait.

3 votes

Quelqu'un peut-il m'indiquer la partie de la spécification du langage où ils sont définis ? Je ne trouve pas "switch expression". mentionné .

50voto

ernest_k Points 14807

Selon l'expression de l'interrupteur JEP une expression switch est une expression poly :

Une expression switch est une expression poly ; si le type de la cible est connu, ce type est poussé vers le bas dans chaque bras. Le type d'une expression switch est son type cible, s'il est connu ; sinon, un type autonome est calculé en combinant les types de chaque bras du cas.

Comme vous n'avez pas de type cible, l'expression n'est pas vérifiée pour correspondre à un type donné, ce qui est attendu.

Vous pouvez vérifier cela en remplaçant var avec un type :

int y = switch (0) {
    case 0 -> '0';
    case 1 -> 0.0F;
    case 2 -> 2L;
    case 3 -> true;
    default -> 4;
};

Dans mon shell, cela échoue avec :

|  Error:
|  incompatible types: bad type in switch expression
|      possible lossy conversion from float to int
|      case 1 -> 0.0F;
|                ^--^
|  Error:
|  incompatible types: bad type in switch expression
|      possible lossy conversion from long to int
|      case 2 -> 2L;
|                ^^
|  Error:
|  incompatible types: bad type in switch expression
|      boolean cannot be converted to int
|      case 3 -> true;
|                ^--^

Mais si vous supprimez boolean :...

Cela devrait suffire pour voir comment le type autonome est déterminé ( règles ici ) :

Le type d'expression d'un commutateur autonome est déterminé comme suit :

  • Si les expressions de résultat ont toutes le même type (qui peut être le type null), alors c'est le type de l'expression de commutation.

  • Sinon, si le type de chaque expression de résultat est booléen ou booléenne, une conversion unboxing (5.1.8) est appliquée à chaque expression de résultat de type booléen, et l'expression de commutation a le type booléen.

  • Sinon, si le type de chaque expression de résultat est convertible en un type numérique (5.1.8), le type de l'expression de commutation est le résultat de la promotion numérique (5.6) appliquée aux expressions de résultat.

  • Sinon, la conversion en boîte (5.1.7) est appliquée à chaque expression de résultat qui a un type primitif, après quoi le type de l'expression de commutation est le résultat de l'application de la conversion en boîte (5.1.10) à la limite supérieure la plus basse (4.10.4) des types des expressions de résultat.

D'après ce que je vois, lorsque l'on supprime l'expression booléenne, il ne reste que des expressions numériques ( char '0' ( int 48 ) est promu à float 48.0 ). Voir le troisième point ci-dessus.

Et pour savoir pourquoi float est le type du résultat, voir le Contextes numériques section.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X