L'instruction switch en Java
Utilisez l'instruction switch en Java pour brancher sur des valeurs, avec des étiquettes case, break, default et le comportement de fall-through.
Lorsque vous devez comparer une seule valeur contre de nombreuses possibilités, une longue chaîne if/else if devient rapidement bruyante. L'instruction switch est l'alternative compacte de Java — lire la valeur une seule fois, sauter au case correspondant, exécuter son bloc.
Syntaxe de base
switch (value) {
case label1:
// body
break;
case label2:
// body
break;
default:
// body
break;
}Un petit exemple :
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Other");
break;
}Le switch saute à case 3:, affiche Wednesday, rencontre break et sort.
Le break est essentiel
Sans break, l'exécution tombe dans le cas suivant — même si son étiquette ne correspond pas. C'est une fonctionnalité délibérée du switch de style C, mais c'est la source d'innombrables bugs dans le code Java :
switch (day) {
case 1:
System.out.println("Monday");
// no break!
case 2:
System.out.println("Tuesday");
break;
}Quand day == 1, cela affiche à la fois Monday et Tuesday. Ajoutez toujours break sauf si vous souhaitez intentionnellement un fall-through.
Fall-through intentionnel
Parfois le fall-through est exactement ce que vous voulez — regrouper plusieurs étiquettes sous le même bloc :
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("Weekday");
break;
case 6:
case 7:
System.out.println("Weekend");
break;
}Lorsque vous faites cela intentionnellement, ajoutez un commentaire // fall through pour que les relecteurs ne pensent pas que vous avez oublié un break. (La nouvelle syntaxe d'expression switch — couverte dans le chapitre suivant — corrige entièrement ce piège.)
Quelles valeurs peut accepter un switch ?
Un switch traditionnel accepte :
- Tous les types entiers :
byte,short,int,char - Leurs wrappers boxés :
Byte,Short,Integer,Character String(depuis Java 7)- Les constantes
enum
Non autorisés : long, float, double, boolean, ou des objets arbitraires. Pour ceux-là, utilisez if/else.
String role = "admin";
switch (role) {
case "admin":
System.out.println("Full access");
break;
case "editor":
System.out.println("Write access");
break;
case "viewer":
System.out.println("Read access");
break;
default:
System.out.println("No access");
break;
}La comparaison de chaînes dans un switch utilise la sémantique String.equals — sensible à la casse. Un point délicat : effectuer un switch sur un String (ou toute valeur boxée/enum) qui est null lève une NullPointerException. Vérifiez la valeur null avant le switch, ou gérez-la dans un garde :
if (role == null) {
System.out.println("No role");
} else {
switch (role) {
case "admin":
System.out.println("Full access");
break;
// ...
}
}default — le cas attrape-tout
default s'exécute quand aucun case ne correspond. Ce n'est pas obligatoire, mais l'inclure est une bonne pratique ; cela rend explicite le comportement pour les valeurs inattendues.
default n'a pas besoin d'être en dernier. Par convention il se place en bas, mais le compilateur l'accepte n'importe où — l'exécution tombe dedans comme pour tout autre case si vous oubliez un break.
Règles à garder en tête
Quelques règles imposées par le compilateur piègent souvent les développeurs :
- Les étiquettes de case doivent être des constantes de compilation. Vous pouvez utiliser des littéraux (
case 3:), des constantesfinal, ou des noms d'enum— mais pas une variable ni un appel de méthode.case x:oùxest une variable non-finale ne compilera pas. - Les étiquettes doivent être uniques. Deux entrées
case 3:dans le même switch sont une erreur de compilation. - Tous les cases partagent la même portée. Une variable déclarée dans un case est visible dans les autres, ce qui peut créer des conflits. Enveloppez le corps d'un case dans des accolades
{ }lorsque vous avez besoin d'une variable locale limitée à ce case :
switch (day) {
case 1: {
int hours = 8;
System.out.println(hours);
break;
}
case 2:
// `hours` is not visible here
break;
}Utiliser switch avec enum
enum et switch forment une paire naturelle. Dans un switch sur une valeur d'enum, vous n'avez pas besoin de qualifier le nom de la constante :
enum Status { PENDING, ACTIVE, DONE }
Status s = Status.ACTIVE;
switch (s) {
case PENDING: // not Status.PENDING
System.out.println("Waiting...");
break;
case ACTIVE:
System.out.println("In progress");
break;
case DONE:
System.out.println("Finished");
break;
}Un exemple pratique
Et ensuite
Java 14 a introduit les expressions switch, qui retournent une valeur, éliminent le fall-through et prennent en charge les cases à étiquettes multiples — le code Java moderne les préfère dès lors que vous ciblez Java 14 ou plus récent.