web-dev-qa-db-fra.com

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

J'accepte 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 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.

43
Ilya

Selon l'expression de commutateur JEP , une expression de commutateur est une expression poly:

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

Parce que 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 le vérifier en remplaçant var par 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 booléen: ...

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

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

  • Si les expressions de résultat ont toutes le même type (qui peut être le type nul), c'est le type de l'expression de commutation.
  • Sinon, si le type de chaque expression de résultat est booléen ou booléen, une conversion de décodage (5.1.8) est appliquée à chaque expression de résultat de type booléen et l'expression de commutateur 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 de boxe (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 de capture (5.1.10) à la limite la moins haute (4.10.4 ) des types d'expressions de résultat.

Pour autant que je puisse voir, lorsque vous supprimez l'expression booléenne, vous vous retrouvez avec des expressions numériques (char'0' (int 48) est promu float48.0). Voir troisième puce ci-dessus.

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

48
ernest_k