Expressions switch en Java
Expressions switch modernes en Java avec syntaxe fléchée, yield et correspondance de motifs exhaustive.
Java 14 a promu les expressions switch au rang de fonctionnalité standard du langage. Elles s'appuient sur l'instruction switch traditionnelle avec trois améliorations majeures : elles produisent une valeur, elles utilisent une syntaxe fléchée plus claire, et elles rendent le fall-through impossible. Si vous utilisez Java 14 ou une version plus récente, préférez-les.
Ce chapitre couvre la syntaxe fléchée, le mot-clé yield pour les corps de blocs, la vérification d'exhaustivité, et la correspondance de motifs basée sur les types qui est devenue standard en Java 21. À la fin, vous saurez quand utiliser une expression switch plutôt qu'une chaîne if/else.
Instruction vs. expression
L'instruction switch traditionnelle est un statement : il fait quelque chose (exécute des effets de bord) mais ne produit aucune valeur. Une expression switch évalue une valeur que vous pouvez assigner, retourner ou passer à une méthode. Cette unique différence conditionne tout le reste de cette page — parce que le résultat est utilisé, le compilateur peut exiger que chaque branche produise une valeur et qu'aucune entrée ne passe inaperçue.
Syntaxe sous forme fléchée
String day = "TUE";
String label = switch (day) {
case "MON", "TUE", "WED", "THU", "FRI" -> "weekday";
case "SAT", "SUN" -> "weekend";
default -> "unknown";
};Trois choses à remarquer :
- Le
switchentier est une expression — il évalue à une valeur que vous pouvez assigner (notez le;final). - Chaque case utilise
->au lieu de:. La partie droite est une instruction ou expression unique. - Plusieurs étiquettes sont autorisées dans un même case, séparées par des virgules. Pas de
break, pas de fall-through.
Corps de bloc avec yield
Si un case nécessite plusieurs instructions, utilisez un bloc — et à l'intérieur du bloc, retournez la valeur avec yield :
int score = 78;
String grade = switch (score / 10) {
case 10, 9 -> "A";
case 8 -> "B";
case 7 -> {
System.out.println("close to B");
yield "C";
}
case 6 -> "D";
default -> "F";
};yield est comme return, mais pour l'expression switch — il définit la valeur de ce switch et quitte le case. (Ne le confondez pas avec return, qui quitterait la méthode englobante.)
Vous n'avez besoin de yield qu'à l'intérieur d'un bloc ({ ... }). Un case à expression unique comme case 8 -> "B"; retourne déjà sa valeur directement, donc ajouter yield serait une erreur de compilation.
yield est un mot-clé contextuel : il n'agit comme mot-clé qu'à l'intérieur d'un bloc switch. Le code qui utilisait yield comme nom de variable ou de méthode avant Java 14 compile toujours, donc l'adoption des expressions switch ne casse jamais les identifiants existants.
Les instructions fonctionnent toujours
Vous pouvez également utiliser la syntaxe fléchée pour des effets de bord, auquel cas il s'agit d'une instruction, pas d'une expression :
switch (day) {
case "MON", "TUE", "WED", "THU", "FRI" -> System.out.println("weekday");
case "SAT", "SUN" -> System.out.println("weekend");
default -> System.out.println("unknown");
}L'avantage par rapport à l'ancienne forme : pas de break, pas de bugs de fall-through, plus les cases multi-étiquettes vus ci-dessus.
Exhaustivité
Lorsqu'une expression switch assigne à une variable, le compilateur exige que chaque entrée possible produise une valeur. Pour un enum, cela signifie soit couvrir toutes les constantes, soit fournir un default :
enum Status { PENDING, ACTIVE, DONE }
Status s = Status.ACTIVE;
String label = switch (s) {
case PENDING -> "waiting";
case ACTIVE -> "running";
case DONE -> "complete";
}; // no default needed — all enum values are coveredSi vous ajoutez ultérieurement une nouvelle constante à l'enum et oubliez de mettre à jour le switch, le compilateur vous le signalera. C'est une forte garantie de correction que vous n'obtenez pas avec if/else.
Correspondance de motifs (Java 21+)
Java 21 a rendu la correspondance de motifs pour switch une fonctionnalité standard. Vous pouvez switcher sur le type d'une valeur, et la lier à une variable typée à l'intérieur du case :
Object o = 42;
String description = switch (o) {
case Integer i when i < 0 -> "negative int: " + i;
case Integer i -> "non-negative int: " + i;
case String s -> "string of length " + s.length();
case null -> "null value";
default -> "something else";
};La clause when est une garde — elle affine un case avec une condition booléenne. Cela remplace de nombreuses chaînes instanceof, et elle se marie naturellement avec les fonctionnalités plus larges de correspondance de motifs.
Deux règles à garder en tête :
- Un
switchtraditionnel rejette un sélecteurnullavec uneNullPointerException. Un switch de motifs peut inclure uncase nullexplicite — sans lui, unnulllance toujours une exception. Il n'est plus possible de laisser passer silencieusement unnulldans le switch sans s'en apercevoir. - Les cases sont testés de haut en bas, donc ordonnez du plus spécifique au plus général. Le
case Integer i when i < 0gardé doit venir avant lecase Integer isimple, sinon le case non gardé absorberait tous les entiers en premier.
Un exemple pratique
Prochaine étape
Nous avons couvert les conditionnelles. Viennent ensuite les boucles : la boucle while est la plus simple d'entre elles.