Java Switch-Anweisung

1. Übersicht

In diesem Tutorial erfahren Sie, was die switch- Anweisung ist und wie sie verwendet wird.

Mit der switch- Anweisung können wir mehrere verschachtelte if-else- Konstrukte ersetzen und so die Lesbarkeit unseres Codes verbessern.

Switch hat sich im Laufe der Zeit weiterentwickelt - neue unterstützte Typen wurden hinzugefügt, insbesondere in Java 5 und 7. Außerdem wird es weiterentwickelt - Switch- Ausdrücke werden wahrscheinlich in Java 12 eingeführt.

Im Folgenden werden einige Codebeispiele aufgeführt, um die Verwendung der switch- Anweisung, die Rolle der break- Anweisung, die Anforderungen an die switch- Argument- / case- Werte und den Vergleich von Zeichenfolgen in einer switch- Anweisung zu demonstrieren .

Fahren wir mit dem Beispiel fort.

2. Anwendungsbeispiel

Angenommen, wir haben die folgenden verschachtelten if-else- Anweisungen:

public String exampleOfIF(String animal) { String result; if (animal.equals("DOG") || animal.equals("CAT")) { result = "domestic animal"; } else if (animal.equals("TIGER")) { result = "wild animal"; } else { result = "unknown animal"; } return result; }

Der obige Code sieht nicht gut aus und ist schwer zu pflegen und zu begründen. Um die Lesbarkeit zu verbessern, können wir hier eine switch- Anweisung verwenden:

public String exampleOfSwitch(String animal) { String result; switch (animal) { case "DOG": result = "domestic animal"; break; case "CAT": result = "domestic animal"; break; case "TIGER": result = "wild animal"; break; default: result = "unknown animal"; break; } return result; }

Wie oben gezeigt, vergleichen wir den Schalter Argument Tier mit den verschiedenen Fallwerte. Wenn keiner der case- Werte dem Argument entspricht, wird der Block unter der Standardbezeichnung ausgeführt.

Einfach ausgedrückt wird die break- Anweisung verwendet, um eine switch- Anweisung zu beenden.

3. Die break- Anweisung

Obwohl die meisten switch- Anweisungen im wirklichen Leben implizieren, dass nur einer der case- Blöcke ausgeführt werden sollte, ist die break- Anweisung erforderlich, um einen Switch nach Abschluss des Blocks zu beenden.

Wenn wir vergessen, eine Pause zu schreiben , werden die darunter liegenden Blöcke ausgeführt.

Um dies zu demonstrieren, lassen wir die break- Anweisungen weg und fügen die Ausgabe für jeden Block zur Konsole hinzu:

public String forgetBreakInSwitch(String animal) { switch (animal) { case "DOG": System.out.println("domestic animal"); default: System.out.println("unknown animal"); } }

Lassen Sie uns diesen Code vergessenBreakInSwitch ( "DOG") ausführen und die Ausgabe überprüfen , um zu beweisen, dass alle Blöcke ausgeführt werden:

domestic animal unknown animal

Wir sollten also vorsichtig sein und break- Anweisungen am Ende jedes Blocks hinzufügen , es sei denn, es ist erforderlich, den Code unter der nächsten Bezeichnung zu durchlaufen.

Der einzige Block, in dem eine Unterbrechung nicht erforderlich ist, ist der letzte. Durch Hinzufügen einer Unterbrechung zum letzten Block wird der Code jedoch weniger fehleranfällig.

Wir können dieses Verhalten auch nutzen, um break auszulassen , wenn derselbe Code für mehrere case-Anweisungen ausgeführt werden soll. Schreiben wir das Beispiel im vorherigen Abschnitt neu, indem wir die ersten beiden Fälle zusammenfassen:

public String exampleOfSwitch(String animal) { String result; switch (animal) { case "DOG": case "CAT": result = "domestic animal"; break; case "TIGER": result = "wild animal"; break; default: result = "unknown animal"; break; } return result; }

4. Schalter Argument und Fall Values

Lassen Sie uns nun die zulässigen Arten von switch- Argumenten und case- Werten, die Anforderungen für sie und die Funktionsweise der switch- Anweisung mit Strings diskutieren .

4.1. Datentypen

Wir können nicht alle Arten von Objekten und Grundelementen in der switch- Anweisung vergleichen. Ein Schalter funktioniert nur mit vier Grundelementen und ihren Wrappern sowie mit dem Aufzählungstyp und der String- Klasse:

  • Byte und Byte
  • kurz und kurz
  • int und Integer
  • char und Character
  • Aufzählung
  • String

Der Zeichenfolgentyp ist in der switch- Anweisung ab Java 7 verfügbar .

Der Aufzählungstyp wurde in Java 5 eingeführt und ist seitdem in der switch- Anweisung verfügbar .

Wrapper-Klassen sind seit Java 5 ebenfalls verfügbar.

Natürlich Schalter Argument und Fall - Werte sollten vom gleichen Typ sein.

4.2. Keine Nullwerte

Wir können den Nullwert nicht als Argument an eine switch- Anweisung übergeben . Wenn wir dies tun, löst das Programm anhand unseres ersten Switch- Beispiels eine NullPointerException aus :

@Test(expected=NullPointerException.class) public void whenSwitchAgumentIsNull_thenNullPointerException() { String animal = null; Assert.assertEquals("domestic animal", s.exampleOfSwitch(animal)); }

Natürlich können wir auch nicht null als Wert an die Groß- / Kleinschreibung einer switch- Anweisung übergeben. Wenn wir das tun, wird der Code nicht kompiliert.

4.3. Fallwerte als Compile-Zeitkonstanten

Wenn wir versuchen, den DOG- Fallwert durch die Variable dog zu ersetzen, wird der Code erst kompiliert, wenn wir die Variable dog als final markieren :

final String dog="DOG"; String cat="CAT"; switch (animal) { case dog: //compiles result = "domestic animal"; case cat: //does not compile result = "feline" }

4.4. String- Vergleich

Wenn eine switch- Anweisung den Gleichheitsoperator zum Vergleichen von Zeichenfolgen verwendet, können wir ein mit dem neuen Operator erstelltes String- Argument nicht korrekt mit einem String- Fallwert vergleichen.

Glücklicherweise verwendet der Switch- Operator die Methode equals () unter der Haube .

Lassen Sie uns dies demonstrieren:

@Test public void whenCompareStrings_thenByEqual() { String animal = new String("DOG"); assertEquals("domestic animal", s.exampleOfSwitch(animal)); }

5. Wechseln Sie die Ausdrücke

JDK 13 is now available and brings an improved version of a new feature first introduced in JDK 12: the switch expression.

In order to enable it, we need to pass –enable-preview to the compiler.

5.1. The New switch Expression

Let's see what the new switch expression looks like when switching over months:

var result = switch(month) { case JANUARY, JUNE, JULY -> 3; case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1; case MARCH, MAY, APRIL, AUGUST -> 2; default -> 0; }; 

Sending in a value like Month.JUNE would set result to 3.

Notice that the new syntax uses the ->operator instead of the colon we're used to with switch statements. Also, there's no break keyword: The switch expression doesn't fall through cases.

Another addition is the fact that we can now have comma-delimited criteria.

5.2. The yield Keyword

Going a bit further, there's a possibility to obtain fine-grained control over what's happening on the right side of the expression by using code blocks. In such a case, we need to use the keyword yield:

var result = switch (month) { case JANUARY, JUNE, JULY -> 3; case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1; case MARCH, MAY, APRIL, AUGUST -> { int monthLength = month.toString().length(); yield monthLength * 4; } default -> 0; };

While our example is a bit arbitrary, the point here is that we've got access to more of the Java language here.

5.3. Returning Inside switch Expressions

As a consequence of the distinction between switch statements and switch expressions, it is possible to return from inside a switch statement, but we're not allowed to do so from within a switch expression.

The following example is perfectly valid and will compile:

switch (month) { case JANUARY, JUNE, JULY -> { return 3; } default -> { return 0; } }

However, the following code will not compile, as we are trying to return outside of an enclosing switch expression:

var result = switch (month) { case JANUARY, JUNE, JULY -> { return 3; } default -> { return 0; } };

5.4. Exhaustiveness

When using switch statements, it doesn't really matter if all cases are covered.

The following code, for example, is perfectly valid and will compile:

switch (month) { case JANUARY, JUNE, JULY -> 3; case FEBRUARY, SEPTEMBER -> 1; }

For switch expressions though, the compiler insists that all possible cases are covered. The following code snippet, for example, would not compile, as there's no default case and not all possible cases are covered:

var result = switch (month) { case JANUARY, JUNE, JULY -> 3; case FEBRUARY, SEPTEMBER -> 1; }

The switch expression, however, will be valid when all possible cases are covered, like in the following example:

var result = switch (month) { case JANUARY, JUNE, JULY -> 3; case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1; case MARCH, MAY, APRIL, AUGUST -> 2; }

Please note that the above code snippet does not have a default case. As long as all cases are covered, the switch expression will be valid.

6. Conclusion

In diesem Tutorial haben wir die Feinheiten der Verwendung der switch- Anweisung in Java kennengelernt. Wir können anhand der Lesbarkeit und der Art der verglichenen Werte entscheiden, ob ein Schalter verwendet werden soll.

Die switch-Anweisung ist ein guter Kandidat für Fälle, in denen wir eine begrenzte Anzahl von Optionen in einem vordefinierten Satz haben (z. B. Wochentage). Andernfalls müssten wir den Code jedes Mal ändern, wenn ein neuer Wert hinzugefügt oder entfernt wird, was möglicherweise nicht möglich ist. In diesen Fällen sollten wir andere Ansätze wie Polymorphismus oder andere Entwurfsmuster wie Command berücksichtigen.

Wie immer ist der vollständige JDK 8-Code und JDK 13-Code auf GitHub verfügbar.