Tech Archive Help

06 Java – Verzweigungen

Verzweigungen (engl. Branches) können den Programmverlauf ändern. Welche Code-Teile ausgeführt werden, hängt von den Bedingungen (engl. Conditions) ab. Java bietet drei Sprachkonstrukte um Verzweigungen realisieren zu können.

if-else

Das am häufigsten verwendete Sprachkonstrukt ist if-else. Hier kommen die Keywords if und else zum Einsatz. Eine if-Abfrage beginnt mit dem Keyword if gefolgt von der Bedingung und der Blockanweisung die ausgeführt wird, wenn die Condition true ergibt.

if (condition) { // Code... }
int n = 7; if (n <= 10) { System.out.println("n is less than or equal to 10!"); }

Mehrstufige Verzweigungen sind mit else if möglich. Dadurch wird der zutreffende Block ausgeführt und alle weiteren übersprungen.

int n = 7; if (n <= 10) { System.out.println("n is less than or equal to 10!"); } else if (n <= 20) { System.out.println("n is less than or equal to 20!"); }

Der else-Block bietet einen alternativen Code-Block, der ausgeführt wird, wenn alle vorherigen Bedingungen nicht zutreffen.

int n = 7; if (n <= 10) { System.out.println("n is less than or equal to 10!"); } else if (n <= 20) { System.out.println("n is less than or equal to 20!"); } else { System.out.println("n is greater than 20!!"); }

Die Reihenfolge ist zu beachten. Würde die n <= 20-Abfrage wie im Folgenden an erster Stelle stehen, würde die Blockanweisung mit der Bedingung n <= 10 niemals ausgeführt werden.

int n = 7; if (n <= 20) { System.out.println("n is less than or equal to 20!"); } else if (n <= 10) { System.out.println("n is less than or equal to 10!"); } else { System.out.println("n is greater than 20!"); }

Die geschweiften Klammern können weggelassen werden, wenn nur eine Anweisung auf die Bedingung folgt.

int n = 7; if (n <= 10) System.out.println("n is less than or equal to 10!");

Zu beachten ist, dass im folgenden Beispiel die zweite Ausgabe immer ausgeführt wird. Nur die erste Anweisung ohne die geschweiften Klammern besteht in Abhängigkeit zur Bedingung.

int n = 7; if (n <= 10) System.out.println("n is less than or equal to 10!"); System.out.println("n = " + n);

Bedingungen können auch verknüpft werden.

int n = 13; if (n >= 10 && < 20) { System.out.println("n is between 10 and 20!"); }

Auch die Negierung von Bedingungen ist möglich.

int n = 7; if (!(n >= 10 && < 20)) { System.out.println("n isn't between 10 and 20!"); }

switch-case

Eine Alternative zu if-else ist das switch-case-Konstrukt. Diese bietet sich als Kurzform gerade für speziell angehäufte if-Abfragen an. Verwendete Keywords sind switch, case, default und break.

Das switch-case-Konstrukt erlaubt die Überprüfung von:

switch-case vs. if-else

Die einzelnen Cases müssen mit einer break-Anweisung beendet werden. Ansonsten wird auch der nachfolgende Case ausgeführt.

int option = 2; if (option == 1) { System.out.println("Option 1 was chosen."); } else if (option == 2) { System.out.println("Option 2 was chosen."); } else if (option == 3) { System.out.println("Option 3 was chosen.); } else { System.out.println("This option doesn't exist."); }
int option = 2; switch (option) { case 1: System.out.println("Option 1 was chosen."); break; case 2: System.out.println("Option 2 was chosen."); break; case 3: System.out.println("Option 3 was chosen."); break; default: System.out.println("This option doesn't exist."); }

Syntaktische Änderungen in Java 12, 13 und 14

Seit Java 12 gab es einige Änderungen und syntaktische Anpassungen, welche in Java 13 nochmal verändert und in Java 14 fest integriert wurden. Es ist nun möglich mehrere Ausdrücke für einen Case durch Kommas getrennt zusammenzufassen.

int option = 2; switch (option) { case 1: System.out.println("Option 1 was chosen."); break; case 2, 3: System.out.println("Option 2 or 3 was chosen."); break; default: System.out.println("This option doesn't exist."); }

Seit Java 14 ist nun auch die folgende Syntax möglich. Implizit beendet ein break den Anweisungsblock. Daher muss dieser nicht selbst hinzugefügt werden.

int option = 2; switch (option) { case 1 -> { System.out.println("Option 1 was chosen."); } case 2 -> { System.out.println("Option 2 was chosen."); } case 3 -> { System.out.println("Option 3 was chosen."); } default -> { System.out.println("This option doesn't exist."); } }

Auch hier können die Klammern bei einzelnen Anweisungen weggelassen werden.

int option = 2; switch (option) { case 1: System.out.println("Option 1 was chosen."); break; case 2: System.out.println("Option 2 was chosen."); break; case 3: System.out.println("Option 3 was chosen."); break; default: System.out.println("This option doesn't exist."); }
int option = 2; switch (option) { case 1 -> System.out.println("Option 1 was chosen."); case 2 -> System.out.println("Option 2 was chosen."); case 3 -> System.out.println("Option 3 was chosen."); default -> System.out.println("This option doesn't exist."); }

switch case – yield

Anweisungen liefern normalerweise keinen Rückgabewert. Seit Java 14 ist auch dies möglich.

int monthNumber = 3; String month = switch (monthNumber) { case 1 -> "January"; case 2 -> "February"; case 3 -> "March"; case 4 -> "April"; case 5 -> "May"; case 6 -> "June"; case 7 -> "July"; case 8 -> "August"; case 9 -> "September"; case 10 -> "October"; case 11 -> "November"; case 12 -> "December"; default -> "Unknown month"; }; System.out.println(month); // March

Wird in solchen Fällen mit Blockanweisungen gearbeitet, muss auch dieser Block ein Ergebnis zurückliefern. Hier kommt das Contextual Keyword yield ins Spiel. Dieses findet nur in switch-case-Konstrukten Anwendung.

int monthNumber = 3; String month = switch (monthNumber) { case 1 -> "January"; case 2 -> "February"; case 3 -> { System.out.println("March was chosen."); yield "March"; } case 4 -> "April"; case 5 -> "May"; case 6 -> "June"; case 7 -> "July"; case 8 -> "August"; case 9 -> "September"; case 10 -> "October"; case 11 -> "November"; case 12 -> "December"; default -> "Unknown month"; }; System.out.println(month); // March

switch-case mit versiegelten Klassen

Mit dem Konzept der versiegelten Klassen (sealed classes), das ab Java 15 eingeführt und mit Java 17 finalisiert wurde, gibt es eine enge Integration mit switch. Wenn eine Klasse als sealed deklariert ist und nur eine festgelegte Gruppe von Unterklassen besitzt, kann ein switch auf Objekte dieser Klasse garantieren, dass alle möglichen Unterklassen abgedeckt sind.

public sealed interface Shape permits Circle, Rectangle, Triangle {} public final class Circle implements Shape {} public final class Rectangle implements Shape {} public final class Triangle implements Shape {} public String describeShape(Shape shape) { return switch (shape) { case Circle c -> "Circle"; case Rectangle r -> "Rectangle"; case Triangle t -> "Triangle"; // No 'default' necessary, since all allowed types are covered. }; }

Ternäre Operator

Der ternäre Operator ist der einzige Operator der 3 Operanden verwendet. Er wird häufig angewendet um schnell den einen oder anderen Ausdruck zu berechnen, da er in einer Zeile geschrieben werden kann. Der Operator besteht aus ? und :.

condition ? expression, if true : expression, if false

Im folgenden Beispiel wird einmal if-else und einmal der ternäre Operator verwendet, um den Maximalwert zu bestimmen.

int x = 7; int y = 13; int max = 0; if (x > y) { max = x; } else { max = y; }
int x = 7; int y = 13; int max = x > y ? x : y;

Kurzschlussauswertung

Die Kurzschlussauswertung (engl. short-circuit evaluation) beschreibt den Abbruch der Auswertung auf der rechten Seite, wenn das Endergebnis bereits feststeht. Mit anderen Worten: Eine Auswertung die nicht (mehr) benötigt wird, wird nicht evaluiert.

Es gibt nur zwei Operatoren die diese Auswertung unterstützen.

Operator

Bezeichnung

Beschreibung

&&

Logisches Und

Die Auswertung endet, sobald das erste Teilergebnis false ergibt. Das Gesamtergebnis ist dann zwingend false.

||

Logisches Oder

Die Auswertung endet, sobald das erste Teilergebnis true ergibt. Das Gesamtergebnis ist dann zwingend true.

int x = 1; int y = 10; if (x == 0 && y == 12) { // Code... }

Da hier eine UND-Verknüpfung besteht, muss sowohl die linke als auch die rechte Auswertung true ergeben, damit die Blockanweisung ausgeführt wird. x == 0 ergibt hier jedoch false. Damit wird der rechte Teil nicht mehr evaluiert, da das Gesamtergebnis bereits feststeht.

Operation mit &&

Auswertung

false && false

false

false && true

false

true && false

false

true && true

true

Operation mit ||

Auswertung

false || false

false

false || true

true

true || false

true

true || true

true

Assertions

Assertions sind Zusicherungen. Sie sind eine Methode zur Laufzeitüberprüfung von Annahmen, die ein Entwickler während der Implementierung seines Codes macht und dienen dazu, potenzielle Fehler während der Entwicklungsphase zu erkennen.

int n = 13; assert n < 10;

Assertions können sowohl mit als auch ohne zusätzliche Meldung geschrieben werden.

int n = 13; assert n < 10 : "n is not less than 10";

Ist eine Bedingung nicht erfüllt, wird ein Error ausgegeben – speziell ein AssertionError.

Assertions müssen explizit aktiviert werden um sie nutzen zu können. Dabei muss beim Programmstart der JVM als Argument -ea übergeben werden, was für enable assertions steht. Standardmäßig sind diese deaktiviert, da sie den eigentlichen Programmfluss verlangsamen können.

Aktivierung von Assertions

  • Current File am oberen Fensterrand. Alternativ Main Menu | Run am linken oberen Fensterrand.

  • Edit Configurations

  • + bzw. Add New Configuration links oben.

  • Application

  • Wählt einen Namen für diese Applikation.

  • Wählt die Main-Klasse mit der main-Methode der Applikation unter dem Writer Build and run.

  • Okay | Modify options | Add VM options

  • Fügt -ea in das Feld VM options hinzu.

  • Okay | Run Main

Übung

Erweitern wir unseren Taschenrechner mit einigen Abfragen und dem Wissen aus Kapitel 5 – Zeichenketten, um nur das Ergebnis einer bestimmten Berechnung auszugeben.

public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("1st number: "); int x = sc.nextInt(); System.out.print("2nd number: "); int y = sc.nextInt(); System.out.print(""" ================= 1: Addition 2: Subtraction 3: Multiplication 4: Division ================= Option:\s"""); int option = sc.nextInt(); switch (option) { case 1 -> System.out.println(x + " + " + y + " = " + (x + y)); case 2 -> System.out.println(x + " - " + y + " = " + (x - y)); case 3 -> System.out.println(x + " * " + y + " = " + (x * y)); case 4 -> System.out.println(x + " / " + y + " = " + (x / y)); default -> System.out.println("This option doesn't exist."); } sc.close(); }
Last modified: 19 August 2024