Instructions étiquetées en Java
Utilisez des étiquettes en Java pour sortir des boucles externes ou passer à leur itération suivante depuis une boucle imbriquée.
Un break simple quitte la boucle la plus interne, et un continue simple saute une itération de celle-ci. Lorsque vous vous trouvez dans des boucles imbriquées et que vous devez contrôler la boucle externe depuis la boucle interne, Java vous offre les instructions étiquetées : un nom que vous pouvez associer à une boucle, et un break ou continue qui la cible par ce nom.
Ce chapitre explique comment définir une étiquette, comment les break et continue étiquetés modifient le flux d'exécution, quand (rarement) les utiliser, et quelles alternatives plus claires privilégier.
C'est ce qui se rapproche le plus d'un goto en Java — et c'est volontairement limité aux boucles (et aux switch).
Définir une étiquette
Une étiquette est un identifiant suivi de deux points, placé immédiatement avant une boucle :
outer:
for (int i = 0; i < 5; i++) {
// ...
}Le nom (outer ici) suit les mêmes règles que n'importe quel identifiant Java. Rien n'impose de l'appeler outer — searchLoop, rows, ou tout autre nom valide convient. Choisissez un nom qui indique pourquoi l'étiquette est là.
break étiqueté
break <label>; quitte la boucle portant cette étiquette, quel que soit le niveau d'imbrication dans lequel vous vous trouvez :
int[][] grid = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int target = 5;
int foundRow = -1, foundCol = -1;
search:
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] == target) {
foundRow = r;
foundCol = c;
break search;
}
}
}
System.out.println("found at " + foundRow + "," + foundCol);Sans le break étiqueté, il faudrait utiliser une variable indicatrice ou restructurer le code. Avec lui, vous sortez des deux boucles en même temps dès que la cible est trouvée.
continue étiqueté
continue <label>; saute le reste de l'itération interne en cours et passe à l'itération suivante de la boucle étiquetée externe :
rowLoop:
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] < 0) {
continue rowLoop; // skip the rest of this row
}
process(grid[r][c]);
}
}Lorsque la boucle interne rencontre une valeur négative, le reste de cette ligne est ignoré et on passe à la ligne suivante.
À utiliser avec parcimonie
Les étiquettes fonctionnent, mais elles peuvent facilement être mal employées. Avant d'en avoir recours, considérez les alternatives :
-
Extraire une méthode utilitaire. Dans une méthode, un simple
returnquitte toutes les boucles d'un coup et est généralement plus clair :static int[] find(int[][] grid, int target) { for (int r = 0; r < grid.length; r++) { for (int c = 0; c < grid[r].length; c++) { if (grid[r][c] == target) return new int[]{r, c}; } } return null; } -
Utiliser un indicateur — légèrement moins élégant, mais explicite et sans
goto:boolean found = false; for (int r = 0; !found && r < grid.length; r++) { for (int c = 0; c < grid[r].length; c++) { if (grid[r][c] == target) { found = true; break; } } } -
Utiliser les streams pour les problèmes de filtrage à la place des boucles imbriquées.
Recourez aux étiquettes lorsque les alternatives nuisent véritablement à la lisibilité — typiquement à deux ou trois niveaux d'imbrication avec une intention claire de « stopper la recherche » ou « passer à l'itération externe suivante ».
Étiquettes et switch
Les étiquettes fonctionnent aussi avec switch, bien que ce soit rare :
sw:
switch (cmd) {
case "x":
if (someCondition) break sw;
// ...
break;
}En pratique, cela n'apporte aucune clarté supplémentaire par rapport à un break ordinaire.
Exemple concret
Prochaine étape
Vous avez terminé les chapitres sur le flux de contrôle : les conditionnelles, l'opérateur ternaire, les switch, les boucles et les instructions qui les interrompent. La prochaine partie porte sur les méthodes — regrouper des blocs de code pour pouvoir les appeler par leur nom.