Die Switch-Anweisung in Java [] (Die Switch-Anweisung in Java), Lektion, Seite 722479
https://www.purl.org/stefan_ram/pub/switch_java (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
Java-Kurs

Der berechnete Sprung in Java 

Erste Beispiele zum berechneten Sprung

Das folgende Beispiel zeigt die kürzestmögliche Form einer switch -Anweisung. Sie hat allerdings keine Wirkung.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 0 ){ } }}
java.lang.System.out
keine Ausgabe.

Das folgende Beispiel zeigt, daß im Rumpf case -Marken (/ˈkeɪz/-Marken) verwendet werden dürfen. Es hat allerdings immer noch keine Wirkung.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 0 ){ case 1: } }}
java.lang.System.out
keine Ausgabe.

Hinter einer case -Marke dürfen Blockeinträge geschrieben werden. Das folgende Beispiel hat allerdings immer noch keine Wirkung.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 0 )
{ case 1:
java.lang.System.out.println( "1" );
java.lang.System.out.println( "1" ); }}}
java.lang.System.out
keine Ausgabe.

Falls der Wert des Ausdrucks in den switch -Klammern mit dem Wert einer case -Marke übereinstimmt, so wird die Ausführung bei dieser case -Marke fortgesetzt.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 1 )
{ case 1:
java.lang.System.out.println( "1" );
java.lang.System.out.println( "1" ); }}}
java.lang.System.out
1
1

Die Fortsetzung eines Programms an einer anderen Stelle als bei der in einem Block folgenden Anweisung wird auch als Sprung  bezeichnet. Die case -Marke, welche den Punkt, an dem die Ausführung in bestimmten Fällen fortgesetzt wird, kennzeichnen, werden auch Sprungziele  genannt.

Anweisungen vor  der angesprungenen case -Marke werden nicht  ausgeführt. Folgende  Anweisung aber schon.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 1 )
{ case 0:
java.lang.System.out.println( "0" );
java.lang.System.out.println( "0" ); case 1:
java.lang.System.out.println( "1" );
java.lang.System.out.println( "1" ); case 2:
java.lang.System.out.println( "2" );
java.lang.System.out.println( "2" ); }}}
java.lang.System.out
1
1
2
2

Es sind auch mehrere case -Marken direkt hintereinander gestattet.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 1 )
{ case 0:
java.lang.System.out.println( "0" );
java.lang.System.out.println( "0" ); case 1:
case 2:
java.lang.System.out.println( "12" );
java.lang.System.out.println( "12" ); case 3:
case 4:
java.lang.System.out.println( "34" );
java.lang.System.out.println( "34" ); }}}
java.lang.System.out
12
12
34
34

Eine eventuell vorhandene default -Marke (/dɪ ˈfɔlt/-Marke) wird angesprungen, wenn es keine passende case -Marke gibt.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 0 )
{ default: java.lang.System.out.println( "default" ); }}}
java.lang.System.out
default

Syntax des berechneten Sprungs (vereinfacht)

      
.-''''-. .''. .----------. .''.
--->( switch )--->( ( )--->| Ausdruck |--->( ) )------------. .-------------------------->
'-....-' '..' '----------' '..' | |
| |
.-------------------------------------------------------------' |
| |
| .------------------------------. |
| | .----------------------. | |
| .''. | v | V .-. |
'--->( { )---'---'---. .--->'---'--->( } )--------------'
'..' | | '-'
| |
| |
.---------------------' '-------------------------------------------------------.
| |
| .---------------------------------. |
| | | |
| .''''. .------. .-. | .----------------. v |
'---.---.--->( case )--->| Wert |---.--->( : )---.---'---.--->| Blockeintrag |---.---'----'
^ | '....' '------' ^ '-' | ^ '----------------' |
| | | | | |
| | .'''''''. | | '-------------------------'
| '--->( default )------------' |
| '.......' |
| |
'--------------------------------------------'

Typanforderungen (vereinfacht)

Der Ausdruck nach »switch« »(« muß den Typ »int« oder »java.lang.String« haben.

Der Wert nach »case« muß ein konstanter Ausdruck sein, dessen Wert schon durch den Quelltext festgelegt ist, er muß mit dem Typ des Ausdrucks nach »switch« »(« verträglich sein.

Semantik (vereinfacht)

Bei der Ausführung einer Anweisung dieser Art wird zunächst der Ausdruck nach »switch« »(« ausgewertet.

Die Ausführung wird dann in dem Block bei der case -Marke fortgesetzt, deren Wert dem Wert des Ausdrucks gleich ist.

Falls keine  solche Marke existiert, wird die Ausführung nach »default« »:« fortgesetzt – falls in dem Block aber kein »default« »:« vorkommt, dann wird gar nichts weiter gemacht.

Die break -Anweisung

In einen switch -Block darf auch eine break -Anweisung verwendet werden.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 1 ){ case 1: break; }}}
java.lang.System.out
keine Ausgabe.
Syntax der break -Anweisung
        
.-'''-. .-.
--->( break )--->( ; )--->
'-...-' '-'
Semantik der break -Anweisung
Bei Ausführung der break -Anweisung wird die Ausführung des switch -Blocks abgebrochen
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 1 )
{ case 1:
java.lang.System.out.println( 1 );
break;
case 2:
java.lang.System.out.println( 2 ); }}}
java.lang.System.out
1
Genauer gesagt wird die Ausführung des nächsten umgebenden Blocks, der durch eine break -Anweisung abgebrochen werden kann, abgebrochen.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 1 )
{ case 1:
java.lang.System.out.println( 1 );
switch( 2 )
{ case 2:
java.lang.System.out.println( 2 );
break;
case 3:
java.lang.System.out.println( 3 ); }
case 4:
java.lang.System.out.println( 4 ); }}}
java.lang.System.out
1
2
4

Schlüsselwörter

»switch«, »case«, und »break« sind Schlüsselwörter.

Die bisher behandelte Schlüsselwörter

»boolean«, »break«, »case«, »double«, »else«, »if«, »public«, »return«, »int«, »final«, »static«, »switch«, »void«

Strukturierte Programmierung mit switch 

Ein switch -Block genügt im allgemeinen nicht  den Anforderungen der strukturierten Programmierung, weil der switch -Block mehrere  Eingänge (die case -Marken) und mehrere  Ausgänge (die break-Anweisungen) hat oder haben kann. In der strukturierten Programmierung darf aber jeder Block nur einen  Eingang (seinen Anfang) und nur einen  Ausgang (sein Ende) haben. (Der Eingang eines Blocks ist die Stelle jenes Blocks, an welcher mit der Ausführung von Anweisungen aus diesem Block begonnen wird. Der Ausgang eines Blocks ist die Stelle jenes Block, an welcher die Ausführung von Anweisungen aus jenem Block beendet oder abgebrochen wird.)

Durch eine bestimmte Kombination von switch  und break  kann man jedoch die mit einer switch -Anweisung strukturiert programmieren, was im allgemeinen als übersichtlicher angesehen wird. Dazu zerlegt man den switch -Block in eine Folge gedachter Blöcke, deren jeder mit case - oder default -Marken beginnt und mit einer break -Anweisung endet, aber sonst keine weiteren case - oder default -Marken oder break -Anweisungen enthält. Jeder dieser gedachten Blöcke hat denn wieder nur einen Eingang an seinem Anfang und einen Ausgang an seinem Ende. (Beim letzten dieser Blöcke könnte die break -Anweisung auch entfallen.)

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( 1 )
{ case 1:
java.lang.System.out.println( 1 );
break; case 2:
java.lang.System.out.println( 2 );
break; }}}
java.lang.System.out
1

Konstantheit von case -Marken

case -Marken müssen konstant sein, in dem Sinne, daß ihre Werte schon während der Übersetzung des Programms  bekannt sind. Das folgende Programm zeigt einen erlaubten Ausdruck und – auskommentiert – einen nicht erlaubten.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final int i = 1 + 1;
final int j = java.lang.Math.random() > 0.5 ? 0 : 1; switch( 1 )
{ case i:
java.lang.System.out.println( 1 );
break; // case j:
case 1:
java.lang.System.out.println( 2 );
break; }}}

Zeichenfolgen in switch

Auch Zeichenfolgen sind in einer switch -Anweisung erlaubt.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( "alpha" )
{ case "alpha":
java.lang.System.out.println( "alpha" );
break; case "beta":
java.lang.System.out.println( "beta" );
break; }}}
java.lang.System.out
alpha
Main.java
public final class Main
{ public static int schulnote( final java.lang.String text )
{ int result = -1;
switch( text )
{ case "sehr gut": result = 1; break;
case "gut": result = 2; break;
case "befriedigend": result = 3; break; }
return result; } public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( schulnote( "gut" )); }}
transcript
2

Datentypen im switch -Ausdruck

Der Ausdruck in einer switch -Anweisung darf weder boolean  noch double  sein. Notfalls kann man einen Ausdruck entsprechend wandeln, wie das folgende Programm zeigt.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( true ? 1 : 0 )
{ case 0:
java.lang.System.out.println( "false" );
break; case 1:
java.lang.System.out.println( "true" );
break; }}}
java.lang.System.out
true

Nachbildung von if  mit switch 

Eine if -Anweisung kann mit einer switch -Anweisung nachgebildet werden, indem genau einer von zwei gedachten case -Blöcken in Abhängigkeit von einem Wahrheitswert ausgeführt wird.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ switch( true ? 1 : 0 )
{ case 0:
java.lang.System.out.println( "false" );
break; case 1:
java.lang.System.out.println( "true" );
break; }}}
java.lang.System.out
true

Mehrfachverzweigungen

Das klassische Einsatzgebiet einer switch-Anweisung ist die Mehrfachverzweigung in Abhängigkeit von einem Wert. Hier ist switch  besser als if, weil der Ausdruck für den Wert nicht immer wiederholt werden muß. Einige Java-Implementation können in manchen Fällen solche Mehrfachverzweigungen mit switch  auch effizienter ausführen also solche mit if  oder einer bedingten Auswertung.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final double r = java.lang.Math.random();
final int a =( int )( r * 3 + 1 );
if( a == 1 )java.lang.System.out.println( "eins" );
else if( a == 2 )java.lang.System.out.println( "zwei" );
else if( a == 3 )java.lang.System.out.println( "drei" ); }}
java.lang.System.out
zwei
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final double r = java.lang.Math.random();
final int a =( int )( r * 3 + 1 );
switch( a )
{ case 1: java.lang.System.out.println( "eins" ); break;
case 2: java.lang.System.out.println( "zwei" ); break;
case 3: java.lang.System.out.println( "drei" ); break; }}}
java.lang.System.out
zwei

Solche switch -Anweisungen können oft besonders effizient  ausgeführt werden, wenn der Bereich der Werte der case -Marken wie in dem obigen Beispiel direkt aufeinanderfolgende Zahlen  sind. Hier könnte die switch -Anweisung schneller als die entsprechende if -Anweisung sein.

Die obenstehende if -Anweisung zeigt auch, wie eine switch -Anweisung mit einer if -Anweisung nachgebildet werden kann.

Bereiche in switch 

Es ist nicht möglich, in einer switch -Anweisung Zahlenbereiche anzugeben. Manchmal ist es jedoch möglich, statt dessen eine Auflistung von case -Marken zu verwenden.

Es sollen beispielsweise Ziffern ab 1 nach ihrer Größe klassifiziert werden.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final double r = java.lang.Math.random();
final int a =( int )( r * 9 + 1 );
switch( a )
{ case 1: case 2: case 3: java.lang.System.out.println( "klein" ); break;
case 4: case 5: case 6: java.lang.System.out.println( "mittel" ); break;
case 7: case 8: case 9: java.lang.System.out.println( "gross" ); break; }}}
java.lang.System.out
mittel
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final double r = java.lang.Math.random();
final int a =( int )( r * 9 + 1 );
switch( a < 4 ? 0 : a < 7 ? 1 : 2 )
{ case 0: java.lang.System.out.println( "klein" ); break;
case 1: java.lang.System.out.println( "mittel" ); break;
case 2: java.lang.System.out.println( "gross" ); break; }}}
java.lang.System.out
mittel

Programmablaufpläne für die switch -Anweisung

Programmablaufpläne erlauben es, Sprünge durch Pfeile darzustellen.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final double r = java.lang.Math.random();
final int a =( int )( r * 9 + 1 );
switch( a < 4 ? 0 : a < 7 ? 1 : 2 )
{ case 0: java.lang.System.out.println( "klein" ); break;
case 1: java.lang.System.out.print( "mittel" );
case 2: java.lang.System.out.println( "gross" ); break; }}}
java.lang.System.out
mittelgross
Programmablaufplan
                                   |
|
v
.-'-.
.-' '-.
.-' '-.
.----------------- a ? -----------------.
| '-. .-' |
| '-. .-' |
| '-.-' |
| | |
| a < 4 | a>=4 ^ a<7 | sonst
| | |
| | .------------>|
v v | v
------'--------- ------'--------- | ------'---------
/ Ausgabe / / Ausgabe / | / Ausgabe /
/ "klein" und / / "mittel" / | / "gross" und /
/ Zeilenende / / / | / Zeilenende /
---------.------ ---------.------ | ---------.------
| | | |
| '-----------' |
| |
'------------------------>.<------------------------'
|
|
|
v

Wir haben im Programmablaufplan einige Details der Implementation, wie die Verwendung der Werte »0«, »1« und »2« als Sprungziele, weggelassen. So ist der Programmablaufplan übersichtlicher.

Spaghetti-Code

Bei der Darstellung größerer Programme mit vielen Sprunganweisungen, können sich die vielen Pfeile in einem Programmablaufplan auch überkreuzen. Sie erscheinen dann als unübersichtlich wie Spaghettis auf einem Teller. Daher wrd solch unübersichtlicher Code auch als Spaghetti-Code  bezeichnet, und es wird empfohlen Sprunganweisungen in Programmen möglichst zu vermeiden.

Das wirkliche Problem mit „Spaghetti-Code“ ist aber nicht „Unübersichtlichkeit“, sondern die Erschwerung von Überarbeitungen des Codes, wie etwa Erschwerungen des Refaktors „Extrahieren einer Methode“.

Für die switch -Anweisung bedeutet dies, daß die weiter oben vorgestellte strukturierte Form bevorzugt werden sollte.

Struktogramme für die switch -Anweisung

Struktogramme erlauben keine Darstellung von Sprüngen. Wie ihr Name schon nahelegt, sind sie nur für die Darstellung der strukturierten Form der Mehrfachverzweigung geeignet.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final double r = java.lang.Math.random();
final int a =( int )( r * 9 + 1 );
switch( a < 4 ? 0 : a < 7 ? 1 : 2 )
{ case 0: java.lang.System.out.println( "klein" ); break;
case 1: java.lang.System.out.println( "mittel" ); break;
case 2: java.lang.System.out.println( "gross" ); break; }}}
java.lang.System.out
mittel
Struktogramm der Mehrfachverzweigung
.-----------------------------------------------.
|''--.. .'|
| ''--.. .' |
| ''--.. .' |
| | ''--.. .' |
| | ''--.. .' |
| a < 4 | a>=4 ^ a<7 ''-. .' sonst |
|----------------|-----------------|------------|
| | | |
| Ausgabe | Ausgabe | Ausgabe |
| "klein" | "mittel" | "gross" |
| | | |
'-----------------------------------------------'
Struktogramm der Mehrfachverzweigung (vereinfacht)
.-----------------------------------------------.
| a < 4 | a>=4 ^ a<7 | sonst |
|----------------|-----------------|------------|
| | | |
| Ausgabe | Ausgabe | Ausgabe |
| "klein" | "mittel" | "gross" |
| | | |
'-----------------------------------------------'

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram722479 stefan_ram:722479 Die Switch-Anweisung in Java Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd722479, slrprddef722479, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/switch_java