Java Labeled Statements
Verwende Labels in Java, um aus verschachtelten Schleifen äußere Schleifen gezielt zu verlassen oder fortzusetzen.
Ein einfaches break verlässt die innerste Schleife, und ein einfaches continue überspringt eine Iteration davon. Wenn du dich in verschachtelten Schleifen befindest und die äußere Schleife von innen heraus steuern musst, bietet Java Labeled Statements: einen Namen, den du an eine Schleife hängen kannst, und ein break oder continue, das diese Schleife anhand des Namens anspricht.
Dieses Kapitel erklärt, wie man ein Label definiert, wie labeled break und continue den Ablauf verändern, wann man sie (selten) einsetzt und welche saubereren Alternativen man bevorzugen sollte.
Das ist das nächste, was Java einem goto hat — und es ist absichtlich auf Schleifen (und switch) beschränkt.
Ein Label definieren
Ein Label ist ein Bezeichner gefolgt von einem Doppelpunkt, der unmittelbar vor einer Schleife steht:
outer:
for (int i = 0; i < 5; i++) {
// ...
}Der Name (outer hier) folgt denselben Regeln wie jeder Java-Bezeichner. Es gibt keine Anforderung, ihn outer zu nennen — searchLoop, rows oder jeder andere gültige Name funktioniert. Wähle einen Namen, der beschreibt, warum das Label vorhanden ist.
Labeled break
break <label>; verlässt die mit diesem Label markierte Schleife, egal wie tief verschachtelt man sich darin befindet:
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);Ohne das labeled break bräuchte man eine Flag-Variable oder müsste den Code umstrukturieren. Damit verlässt man beide Schleifen gleichzeitig, sobald das Ziel gefunden wurde.
Labeled continue
continue <label>; überspringt den Rest sowohl der aktuellen inneren Iteration als auch fährt mit der nächsten Iteration der bezeichneten äußeren Schleife fort:
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]);
}
}Wenn die innere Schleife auf einen negativen Wert trifft, wird der Rest dieser Zeile übersprungen und wir fahren mit der nächsten Zeile fort.
Sparsam einsetzen
Labels funktionieren, lassen sich aber leicht missbrauchen. Bevor man zu einem Label greift, sollte man zunächst die Alternativen in Betracht ziehen:
-
Eine Hilfsmethode auslagern (method). Innerhalb einer Methode verlässt ein einfaches
returnalle Schleifen auf einmal und ist meist klarer: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; } -
Eine Flag-Variable verwenden — etwas weniger sauber, aber explizit und ohne
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; } } } -
Streams verwenden für Filterprobleme statt verschachtelter Schleifen.
Greife zu Labels, wenn die Alternativen die Lesbarkeit wirklich beeinträchtigen — typischerweise bei zwei oder drei Ebenen Tiefe mit einem klaren "Suche abbrechen"- oder "nächste äußere Iteration"-Intent.
Labels und switch
Labels funktionieren auch mit switch, obwohl das selten vorkommt:
sw:
switch (cmd) {
case "x":
if (someCondition) break sw;
// ...
break;
}In der Praxis bringt dies gegenüber einem einfachen break keine zusätzliche Klarheit.
Ein ausgearbeitetes Beispiel
Wie geht es weiter
Du hast die Kapitel zur Ablaufsteuerung abgeschlossen: Bedingungen, den ternären Operator, switch, Schleifen und die Anweisungen, die sie unterbrechen. Als Nächstes folgt der Teil über Methoden — Codeblöcke in Pakete fassen, die du über einen Namen aufrufen kannst.