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

Die Ausführungswahl

Syntax der Ausführungswahl (vereinfacht)

else (englisch) /ɛls/ „sonst“

Die Ausführungswahl  (eine Möglichkeit der Syntaxbeschreibung)
    .------------------------.     .-''-.     .-----------.
--->| if-Anweisung ohne else |--->( else )--->| Anweisung |--->
'------------------------' '-..-' '-----------'
Die Ausführungswahl  (alternative Variante der Syntaxbeschreibung)
     .--.      .--.     .----------.     .--.     .-----------.     .-''-.     .-----------.
--->( if )--->( ( )--->| Ausdruck |--->( ) )--->| Anweisung |--->( else )--->| Anweisung |--->
'--' '--' '----------' '--' '-----------' '-..-' '-----------'
Die Ausführungswahl  (mit sprechenden Bezeichnungen)
     .--.      .--.     .-----------.     .--.     .------------.     .-''-.     .-------------.
--->( if )--->( ( )--->| Bedingung |--->( ) )--->| Konsequenz |--->( else )--->| Alternative |--->
'--' '--' '-----------' '--' '------------' '-..-' '-------------'

Die Ausführungswahl wird auch if-Anweisung  oder Verzweigung  genannt. Ihr beiden Anweisungen bezeichnet man auch als Zweige  dieser Anweisung.

Der Unterschied zur bedingten Anweisung besteht in der else-Klausel am Ende. (Eine Klausel  ist ein Teil eines Programms, der durch ein Schlüsselwort eingeleitet wird, welches die Bezeichnung der Klausel festlegt.)

Wenn man von einer if-Anweisung  spricht, kann sowohl eine bedingte Ausführung (ohne »else«) als auch eine Ausführungswahl (mit »else«) gemeint sein.

Typanforderungen

Der Ausdruck muß den Typ »boolean« haben.

Schlüsselwörter

»else« ist ein Schlüsselwort.

Die bisher behandelte Schlüsselwörter

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

Semantik der Ausführungswahl (vereinfacht)

Bei der Ausführung einer Anweisung dieser Art wird zunächst der Ausdruck ausgewertet.

Die erste  Anweisung wird genau dann ausgeführt, wenn der Ausdruck true  ist, sonst  (englisch “else ”) wird die zweite  Anweisung ausgeführt.

Der Ausdrück wählt  also aus, welche der beiden Anweisungen ausgeführt  wird.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ if( true )java.lang.System.out.println( "0 true" );
else java.lang.System.out.println( "0 false" );
if( false )java.lang.System.out.println( "1 true" );
else java.lang.System.out.println( "1 false" ); }}
java.lang.System.out
0 true
1 false

Vergleich mit der Auswertungswahl

Die Auswertungswahl  mit »?« und »:« akzeptiert zwei Ausdrücke, die Ausführungswahl  akzeptiert zwei Anweisungen. Beim obigen Beispiel unterscheiden sich die Anweisungen nur in den Ausdrücken, so daß die Verwendung der Auswertungswahl hier eine kürzere  Formulierung mit weniger Wiederholungen erlaubt.

Man kann die Auswertungswahl auch als „ein if  für Ausdrücke“ ansehen.

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

Eine return-Anweisung kann beispielsweise nicht  direkt als Operand in einem »?«-»:«-Operator verwendet werden, da sie eine Anweisung  und kein Ausdruck  ist. Sie muß in einer if-Anweisung stehen.

Umgekehrt kann eine if-Anweisung nicht direkt als Rückgabeausdruck in einer return-Anweisung verwendet werden. Hier ist ein »?«-»:«-Operator nötig.

Initialisierung von Variablen

Eine Java -Implementation stellt sicher, daß benutzte Variablen oder Konstanten initialisiert sind. Dabei ist es gestattet, die Initialisierung erst nach der Deklaration vorzunehmen, solange schon beim Übersetzen erkannt werden kann, daß die Initialisierung auf jeden Fall vor der ersten Benutzung erfolgt sein wird.

Das nächste Programm zeigt Fälle, in denen die Java -Implementation schon bei der Übersetzung erkennen kann, daß alle vorkommenden Konstanten vor ihrer ersten Benutzung (Auslesung) initialisiert wurden.

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

{ final int k;
k = 0;
java.lang.System.out.println( k ); }

{ final int k;
if( java.lang.Math.random() > 0.5 )k = 0;
else k = 1;
java.lang.System.out.println( k ); }

{ final int k;
if( true )k = 0;
java.lang.System.out.println( k ); }

{ final int k;
if( 1 + 1 == 2 )k = 0;
java.lang.System.out.println( k ); }}}

java.lang.System.out
0
0
0
0

Das nächste Programm zeigt einen Fall, in dem die Java -Implementation bei der Übersetzung nicht  erkennen kann, daß alle vorkommenden Konstanten vor ihrer ersten Benutzung (Auslesung) initialisiert wurden. (Dies trifft ja auch tatsächlich nicht zu.)

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final int k;
if( java.lang.Math.random() < 0.5 )k = 0;
java.lang.System.out.println( k ); }}
Konsole
Main.java:5: error: variable k might not have been initialized
java.lang.System.out.println( k ); }}
^

return -Anweisungen *

Wie eine bedingte Ausführung, kann auch eine Verzweigung Rückgabeanweisungen enthalten.

Das folgende Beispiel wird von einer Java -Implementation akzeptiert, da diese erkennen kann, daß k  immer dann initialisiert wird, wenn es auch später ausgelesen wird.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final int k;
if( java.lang.Math.random() < 0.5 )return; else k = 0;
java.lang.System.out.println( k ); }}

Verschachtelte Verzweigungen

Eine Anweisung, die Teil einer if -Anweisung ist, kann ihrerseits auch selber wieder eine if -Anweisung sein.

Folgte ein »else« auf zwei »if«, so kann es Situationen geben, in denen es nicht klar ist, zu welchem der beiden »if« das »else« gehört. Es gehört dann zum zweiten »if«, also zu dem »if«, welches dem »else« am nächsten ist.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ if( true )if( false )java.lang.System.out.println( "1" );
else java.lang.System.out.println( "2" ); }}
java.lang.System.out
2

Soll das »else« statt dessen zum ersten »if« gehören, so kann dies durch entsprechende Klammerung erreicht werden.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ if( true ){ if( false )java.lang.System.out.println( "1" ); }
else java.lang.System.out.println( "2" ); }}
java.lang.System.out
keine Ausgabe

if -Kaskaden

if -Kaskaden  lassen sich an der typischen Folge »else if« erkennen. Dabei handelt es sich aber um nichts anderes als eine Verschachtelung  normaler if -Anweisungen. Sie werden verwendet, wenn es insgesamt mehr als zwei Zweige  geben soll.

Main.java

public final class Main
{

public static java.lang.String deutsch( final int a )
{ final java.lang.String result;
if( a == 0 )result = "Null";
else if( a == 1 )result = "Eins";
else if( a == 2 )result = "Zwei";
else if( a == 3 )result = "Drei";
else result = "Vier";
return result; }

public static void print( final int a )
{ java.lang.System.out.println( a + " ist " + deutsch( a )+ "." ); }

public static void main( final java.lang.String[] args )
{ print( 0 ); print( 1 ); print( 2 ); print( 3 ); print( 4 ); }}

java.lang.System.out
0 ist Null.
1 ist Eins.
2 ist Zwei.
3 ist Drei.
4 ist Vier.

Manchmal können solche Alternativen auch mit weniger »else« formuliert werden.

Main.java

public final class Main
{

public static java.lang.String deutsch( final int a )
{ java.lang.String result = "Vier";
if( a == 0 )result = "Null";
if( a == 1 )result = "Eins";
if( a == 2 )result = "Zwei";
if( a == 3 )result = "Drei";
return result; }

public static void print( final int a )
{ java.lang.System.out.println( a + " ist " + deutsch( a )+ "." ); }

public static void main( final java.lang.String[] args )
{ print( 0 ); print( 1 ); print( 2 ); print( 3 ); print( 4 ); }}

java.lang.System.out
0 ist Null.
1 ist Eins.
2 ist Zwei.
3 ist Drei.
4 ist Vier.

Bei der Formulierung ohne »else« werden aber wahrscheinlich zur Laufzeit mehr Bedingungen geprüft. Außerdem besteht das Risiko, daß sich die Anweisung auch nicht wie beabsichtigt verhält, wenn einer der Zweige eine Änderung vornimmt, welche eine Bedingung beeinflußt, dazu vergleiche man die folgenden beiden Programme.

Main.java
public final class Main
{
public static void print( int a )
{ if( a == 1 ){ java.lang.System.out.println( "Eins." ); a = 0; }
else if( a == 0 ){ java.lang.System.out.println( "nicht Eins." ); a = 1; }
else {} }
public static void main( final java.lang.String[] args )
{ print( 1 ); }}
java.lang.System.out
Eins.
Main.java
public final class Main
{
public static void print( int a )
{ if( a == 1 ){ java.lang.System.out.println( "Eins." ); a = 0; }
if( a == 0 ){ java.lang.System.out.println( "nicht Eins." ); a = 1; }}
public static void main( final java.lang.String[] args )
{ print( 1 ); }}
java.lang.System.out
Eins.
nicht Eins.

Dieses Beispiel zeigt, daß bei einer Mehrfachverzweigung im allgemeinen darauf geachtet werden sollte, die »else« nicht wegzulassen oder zu vergessen. Man kann es auch als eine Illustration der Probleme verstehen, die Variablen mit sich bringen, den das Beispiel wäre so nicht möglich, wenn a  eine Konstante wäre. (Natürlich wurden die Zuweisung an a  hier extra für dieses Beispiel in das Programm geschrieben, aber auch in der Praxis findet man vergleichbare Fälle, die aber für diese Lektion aber unnötig kompliziert wären.)

Das am Anfang dieses Abschnitts gezeigte Programm kann natürlich kürzer  mit bedingten Auswertungen  geschrieben werden.

In diesem Teil des Kurses ist es leider noch nicht einfach, Beispiele mit »else« zu finden, die sich nicht kürzer mit dem ternären Operator schreiben lassen.

Main.java

public final class Main
{

public static java.lang.String deutsch( final int a )
{ return a == 0 ? "Null" : a == 1 ? "Eins" :
a == 2 ? "Zwei" : a == 3 ? "Drei" : "Vier"; }

public static void print( final int a )
{ java.lang.System.out.println( a + " ist " + deutsch( a )+ "." ); }

public static void main( final java.lang.String[] args )
{ print( 0 ); print( 1 ); print( 2 ); print( 3 ); print( 4 ); }}

java.lang.System.out
0 ist Null.
1 ist Eins.
2 ist Zwei.
3 ist Drei.
4 ist Vier.

Refaktor Gleiche Anweisungen in beiden Zweigen *

Eine Anweisung, die in beiden Zweigen vorkommt, kann manchmal vor oder hinter die Verzweigung geschrieben werden.

Vorher
if( b() ){ f(); g(); } else g();
Hinterher
if( b() )f(); g();
Vorher
if( b() ){ f(); g(); } else f();
Nachher
f(); if( b() )g();

Es gibt noch weitere ähnliche Refaktoren dieser Art.

Übungsfragen

Übungsfrage

Was gibt das folgende Programm aus?

Main.java

public final class Main
{

public static java.lang.String deutsch( final int a )
{ java.lang.String result;
if( a == 0 )result = "Null";
if( a == 1 )result = "Eins";
if( a == 2 )result = "Zwei";
if( a == 3 )result = "Drei";
else result = "Vier";
return result; }

public static void print( final int a )
{ java.lang.System.out.println( deutsch( a )); }

public static void main( final java.lang.String[] args )
{ print( 0 ); print( 1 ); print( 2 ); print( 3 ); print( 4 ); }}

Übungsfrage

Was gibt das folgende Programm aus?

Main.java

public final class Main
{

public static void report( final int a )
{ if( a > 1 )java.lang.System.out.println( "a > 1" );
else if( a > 2 )java.lang.System.out.println( "a > 2" );
else if( a > 4 )java.lang.System.out.println( "a > 4" );
else if( a > 8 )java.lang.System.out.println( "a > 8" );
else java.lang.System.out.println( "else" ); }

public static void main( final java.lang.String[] args )
{ report( 10 ); }}

Übungsfrage

Wie kann man die folgende Methodendeklaration verkürzen?

Methodendeklaration
public static void test( final boolean x )
{ final boolean result;
if( x )result = true;
else result = false;
return result; }

Übungsfrage

Die folgende Methodendeklaration, soll eine Methode deklarieren, die true  genau dann ergibt, wenn x  den Wert false  hat.
static boolean isFalse( boolean x )
{ boolean result;
if( x = false )result = true;
else result = false;
return result; }

Wie kann man diese Methodendeklaration korrigieren?

Übungsaufgaben

/   Refaktor

Die folgende Methodendeklarationen enthält einige Wiederholungen von Ausgabeanweisungen. Verkürzen Sie diese Methodendeklaration – bei unverändertem Verhalten – , indem Sie einzelne dieser Ausgabeanweisungen entweder an eine andere Stelle im Quelltext verschiebt oder löschen.

Methodendeklaration
public static void ausgabe( final int zahl )
{ if( zahl > 0 )
{ java.lang.System.out.println( "Die Zahl ist " );
java.lang.System.out.println( "positiv." ); }
else
{ java.lang.System.out.println( "Die Zahl ist " );
java.lang.System.out.println( "nicht " );
java.lang.System.out.println( "positiv." ); }}

/   Refaktor

Die folgende Methode gibt das Maximum zweier int-Werte zurück. Schreiben Sie sie so um, daß statt der if-Anweisung der ternäre Operator verwendet wird.

Methode
public static int max( final int l, final int r )
{ if( l > r )return l; else return r; }

/   Refaktor

Teilen Sie die folgende Methodendeklaration – bei unverändertem Verhalten – auf drei Methodendeklaration auf, deren jede eine der if-Anweisungen enthält.

Eine dieser drei Methoden soll »onCreate« heißen und dasselbe Verhalten zeigen wie die unten gezeigte Methode »onCreate«, dazu kann sie die anderen beiden Methoden als Hilfsmethoden aufrufen.

Methode
public final void onCreate()
{ if( packageManager.hasSystemFeature( android.content.pm.PackageManager.FEATURE_CAMERA ))
{ this.camera = android.hardware.Camera.open();
if( this.camera != null )
{ final android.hardware.Camera.Parameters cameraParameters = camera.getParameters();
if( cameraParameters != null )use( cameraParameters );
else fail( "Can't get camera parameters!" ); }
else fail( "Can't open camera!" ); }
else fail( "System feature camera not available on package manager!" ); }

Übungsaufgaben

/   Methoden zur Abkürzung/Weiterleitung

Ergänzen Sie das folgende Programm um die Deklaration einer Methode »pow« zur Potenzierung.

Main.java

public final class Main
{ ...

public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( pow( 2, 3 )); }}

java.lang.System.out
8

/   Eine Zufallszahlenmethode

Schreiben Sie die Deklaration einer Wertmethode »wert0bis1«, so daß der Wert des Aufrufausdrucks »wert0bis1()« ein zufälliger double-Wert zwischen 0 und 1 ist. Diese Methode soll keine Wirkung haben.

/   Summen-Methode

Schreiben Sie eine int-Methode »sum« welche die Summe ihrer beiden Argumentwerte ergibt und berechnen Sie dann die Summe »2 + 3 + 5« mit Hilfe von Aufrufen dieser Methode (ohne den Operator »+«).

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 stefanram720343 stefan_ram:720343 Die Selektion in Java Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd720343, slrprddef720343, 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/selektion_java