Kontrollstrukturen in Java: Bedingungen, switch und Schleifen sicher einsetzen
Kontrollstrukturen entscheiden, welcher Code ausgeführt wird, wie oft er läuft und wann ein Ablauf endet. Dieser Guide verbindet klassische Bedingungen und Schleifen mit modernen switch-Ausdrücken und robusten Entwurfsmustern.
Das Wichtigste vorab
Kurzfassung: ca. 1 Minute · vollständiger Artikel: ca. 11 Minuten
ifundelsebilden Entscheidungen aus booleschen Bedingungen ab. Frühe Rückgaben können tiefe Verschachtelungen vermeiden.- Moderne
switch-Ausdrücke mit->liefern direkt einen Wert und verhindern unbeabsichtigtes Fall-through. foreignet sich für zählbare Abläufe, die erweiterte for-Schleife für Elemente einer Sammlung undwhilefür bedingungsgesteuerte Wiederholungen.- Bei jeder Schleife müssen Startzustand, Fortsetzungsbedingung und Fortschritt zusammenpassen. Sonst drohen Endlosschleifen oder Fehler an den Grenzen.
breakbeendet,continueüberspringt den restlichen aktuellen Durchlauf. Sparsam eingesetzt sind beide gut lesbar.- Streams ersetzen nicht jede Schleife. Eine Schleife ist oft klarer, wenn der Ablauf Zustände verändert, früh endet oder mehrere Schritte pro Element ausführt.

Ohne Kontrollstrukturen würde ein Programm jede Anweisung genau einmal von oben nach unten ausführen. Bedingungen, Verzweigungen und Schleifen machen daraus einen gesteuerten Ablauf. Entscheidend ist nicht nur die korrekte Syntax: Gute Kontrollflüsse machen Regeln sichtbar, begrenzen Sonderfälle und lassen erkennen, warum und wann ein Abschnitt endet.
Was Kontrollfluss bedeutet
Der Kontrollfluss beschreibt die Reihenfolge, in der Anweisungen ausgeführt werden. Drei Grundideen reichen für die meisten Programme:
Sequenz
Anweisungen laufen nacheinander ab.
Auswahl
Eine Bedingung entscheidet zwischen mehreren Pfaden.
Wiederholung
Ein Block läuft, solange eine Bedingung gilt oder Elemente vorhanden sind.
Methodenaufrufe, Rückgaben und Exceptions beeinflussen den Ablauf zusätzlich. Gute Methoden halten die Zahl der gleichzeitig zu überblickenden Pfade klein.
Entscheidungen mit if und else
Eine if-Anweisung erwartet einen Ausdruck vom Typ boolean. Ist er true, wird der zugehörige Block ausgeführt. else if ergänzt weitere Fälle, else fängt den Rest ab.
int temperatur = 24;
if (temperatur < 0) {
System.out.println("Frost");
} else if (temperatur < 20) {
System.out.println("Kühl");
} else {
System.out.println("Warm");
}
Die Reihenfolge ist Teil der Logik. Sobald eine Bedingung zutrifft, werden die folgenden Zweige derselben Kette übersprungen. Beginne deshalb meist mit dem speziellsten Fall.
Bedingungen lesbar benennen
boolean istVolljaehrig = alter >= 18;
boolean darfTeilnehmen = istVolljaehrig && einwilligungVorhanden;
if (darfTeilnehmen) {
anmeldungBestaetigen();
}
Benannte Zwischenergebnisse sind nicht immer nötig. Bei fachlich wichtigen oder zusammengesetzten Regeln können sie aber mehr erklären als ein langer Ausdruck direkt in der Klammer.
Verschachtelungen mit Guard Clauses reduzieren
Eine Guard Clause behandelt einen ungültigen oder besonderen Fall früh und verlässt danach die Methode. Der normale Ablauf muss dadurch nicht tief eingerückt werden.
static double berechneRabatt(Kunde kunde, double betrag) {
if (kunde == null) {
throw new IllegalArgumentException("Kunde fehlt");
}
if (betrag <= 0) {
return 0.0;
}
if (!kunde.istPremium()) {
return 0.0;
}
return betrag * 0.10;
}
Frühe Rückgaben sind kein Selbstzweck. Sie helfen vor allem dann, wenn sie Vorbedingungen, Abbruchfälle oder Fehler sichtbar vom Hauptfall trennen.
Der bedingte Operator ?:
Der bedingte Operator wählt zwischen zwei Ausdrücken und liefert einen Wert. Für kurze, symmetrische Entscheidungen kann er eine klare Alternative zu einer vollständigen if-Anweisung sein.
String status = bestand >= 60 ? "bestanden" : "nicht bestanden";
Verschachtelte bedingte Operatoren werden schnell schwer lesbar. Sobald Berechnungen, Nebenwirkungen oder mehr als zwei fachliche Fälle beteiligt sind, ist eine normale Verzweigung oder eine eigene Methode meist besser.
Moderne switch-Ausdrücke
Ein switch eignet sich, wenn ein Ausdruck gegen mehrere klar abgegrenzte Fälle geprüft wird. Die moderne Pfeilsyntax verhindert, dass die Ausführung unbeabsichtigt in den nächsten Fall weiterläuft.
enum Prioritaet { NIEDRIG, MITTEL, HOCH }
static int reaktionszeitInStunden(Prioritaet prioritaet) {
return switch (prioritaet) {
case HOCH -> 1;
case MITTEL -> 8;
case NIEDRIG -> 24;
};
}
Weil alle Enum-Konstanten abgedeckt sind, ist kein default-Zweig nötig. Ergänzt jemand später eine neue Konstante, weist der Compiler auf die unvollständige Entscheidung hin. Das macht die Regel wartbarer.
Mehrere Anweisungen und yield
String hinweis = switch (prioritaet) {
case HOCH -> {
protokolliereEskalation();
yield "Sofort bearbeiten";
}
case MITTEL -> "Heute einplanen";
case NIEDRIG -> "In die Warteschlange";
};
Ein Block hinter einem Fall kann mehrere Anweisungen enthalten. yield liefert dann den Wert dieses Falls an den gesamten switch-Ausdruck.
switch-Statement steuert nur den Ablauf. Ein switch-Ausdruck produziert zusätzlich einen Wert und lässt sich beispielsweise direkt einer Variablen zuweisen oder zurückgeben.while und do-while
Eine while-Schleife prüft ihre Bedingung vor jedem Durchlauf. Sie kann daher auch kein einziges Mal ausgeführt werden.
int versuch = 1;
while (versuch <= 3) {
System.out.println("Versuch " + versuch);
versuch++;
}
Bei do-while steht die Prüfung am Ende. Der Schleifenrumpf läuft mindestens einmal:
String eingabe;
do {
eingabe = liesEingabe();
} while (eingabe.isBlank());
Das passt beispielsweise zu Menüs oder Eingaben, bei denen zunächst ein Wert erhoben und erst danach geprüft wird. In vielen anderen Fällen macht eine normale while-Schleife die Eintrittsbedingung deutlicher.
for und die erweiterte for-Schleife
Die klassische for-Schleife bündelt Initialisierung, Fortsetzungsbedingung und Aktualisierung in einer Zeile. Sie eignet sich besonders für zählbare Abläufe und Indexzugriffe.
for (int i = 0; i < 5; i++) {
System.out.println("Index: " + i);
}
Wenn nur die Elemente eines Arrays oder einer Iterable-Collection gebraucht werden, ist die erweiterte for-Schleife meist leichter lesbar:
List namen = List.of("Ada", "Linus", "Grace");
for (String name : namen) {
System.out.println(name);
}
ConcurrentModificationException auslösen. Verwende je nach Aufgabe beispielsweise einen Iterator, removeIf() oder erzeuge eine neue Collection.break, continue und benannte Schleifen
break beendet die nächste umgebende Schleife. continue überspringt den restlichen aktuellen Durchlauf und setzt mit dem nächsten fort.
for (String name : namen) {
if (name == null || name.isBlank()) {
continue;
}
if (name.equals("Ende")) {
break;
}
System.out.println(name);
}
Java unterstützt außerdem benannte Anweisungen, mit denen break oder continue eine äußere Schleife adressieren kann:
suche:
for (int zeile = 0; zeile < matrix.length; zeile++) {
for (int spalte = 0; spalte < matrix[zeile].length; spalte++) {
if (matrix[zeile][spalte] == ziel) {
break suche;
}
}
}
Labels sind legal, aber selten nötig. Wenn die Logik komplex wird oder ein Ergebnis benötigt wird, ist eine ausgelagerte Suchmethode mit früher Rückgabe häufig verständlicher.
Grenzen und Endlosschleifen beherrschen
Für jede Schleife solltest du drei Fragen beantworten können:
- In welchem Zustand beginnt sie?
- Unter welcher Bedingung läuft sie weiter?
- Welche Änderung bringt sie dem Ende näher?
int[] werte = {4, 8, 15, 16, 23, 42};
for (int i = 0; i < werte.length; i++) {
System.out.println(werte[i]);
}
Die Bedingung lautet i < werte.length, nicht i <= werte.length. Da der erste Index 0 ist, liegt der letzte gültige Index genau eins unter der Länge.
Schleife oder Stream?
Streams beschreiben Datenverarbeitung als Pipeline. Für Filtern, Umformen und Aggregieren können sie sehr prägnant sein:
List sichtbareNamen = namen.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(name -> !name.isEmpty())
.toList();
Eine Schleife bleibt häufig klarer, wenn mehrere Zustände verändert werden, der Ablauf an verschiedenen Stellen enden kann, Exceptions pro Element behandelt werden oder die Reihenfolge einzelner Schritte besonders wichtig ist. Wähle die Form, welche die Absicht für Leserinnen und Leser am direktesten ausdrückt.
Kurzvergleich mit Kotlin
In Kotlin sind if und when Ausdrücke und können direkt Werte liefern. when übernimmt viele Aufgaben von Java-switch und kann auch komplexere Bedingungen ausdrücken.
val kategorie = when (punktzahl) {
in 90..100 -> "sehr gut"
in 75..89 -> "gut"
in 60..74 -> "bestanden"
else -> "nicht bestanden"
}
for (index in 0 until 5) {
println(index)
}
Java verwendet für Zahlenbereiche meist Vergleichsausdrücke oder eigene Falllogik; Kotlin bringt Ranges und Progressions direkt in die Sprache ein. In beiden Sprachen gilt: Eine kompakte Schreibweise ist nur dann ein Gewinn, wenn die zugrunde liegende Regel erkennbar bleibt.
Best Practices und typische Fehler
Hilfreiche Gewohnheiten
- Auch bei einzeiligen Zweigen geschweifte Klammern verwenden.
- Komplexe Bedingungen mit sprechenden Namen oder Methoden erklären.
- Ungültige Fälle früh behandeln.
- Bei Enums vollständige
switch-Ausdrücke bevorzugen. - Schleifengrenzen mit leeren und ein-elementigen Daten testen.
Häufige Stolperfallen
- Ein Semikolon direkt hinter
if (...)setzen. - Im klassischen
switchein notwendigesbreakvergessen. <= array.lengthals obere Indexgrenze verwenden.- Die Fortschrittsvariable einer
while-Schleife nicht ändern. - Zu viele Ebenen ineinander verschachteln.
Tests an Grenzen denken
Prüfe Bedingungen nicht nur mit einem „normalen“ Wert, sondern auch knapp darunter, exakt auf der Grenze und knapp darüber. Für Collections gehören eine leere, eine ein-elementige und eine typische mehr-elementige Eingabe zum sinnvollen Mindestumfang.
Glossar
- Bedingung
- Ausdruck vom Typ
boolean, der einen Kontrollpfad steuert. - Zweig
- Einer von mehreren möglichen Ausführungspfaden.
- Iteration
- Ein einzelner Durchlauf einer Schleife.
- Fall-through
- Weiterlaufen vom aktuellen in den nächsten Fall eines klassischen
switch-Statements. - Guard Clause
- Frühe Behandlung eines Sonder- oder Fehlerfalls, meist mit
returnoder Exception. break- Beendet eine Schleife oder einen klassischen
switch-Block. continue- Überspringt den restlichen aktuellen Schleifendurchlauf.
- Off-by-one-Fehler
- Grenzfehler, bei dem ein Durchlauf oder Index zu viel oder zu wenig berücksichtigt wird.
Fazit
Kontrollstrukturen übersetzen Regeln in ausführbare Pfade. if behandelt freie Bedingungen, moderne switch-Ausdrücke ordnen klar definierte Fälle, und Schleifen wiederholen Arbeit kontrolliert. Besonders robust wird der Code, wenn Sonderfälle früh sichtbar sind, Schleifengrenzen bewusst getestet werden und jede Wiederholung einen nachvollziehbaren Weg zum Ende besitzt.



tiny-tool.de
tiny-tool.de