Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage
<< | < | > | >> | API | Kapitel 6 - Anweisungen

## 6.2 Verzweigungen

- 6.2 Verzweigungen
  - 6.2.1 Die if-Anweisung
    - Syntax
    - Bedeutung
    - Dangling else
    - Bedingtes Kompilieren
  - 6.2.2 Die switch-Anweisung
    - Syntax
    - Bedeutung

Verzweigungen in Java dienen wie in allen Programmiersprachen dazu, bestimmte Programmteile nur beim Eintreten vorgegebener Bedingungen, die erst zur Laufzeit bekannt werden, auszuführen. An Verzweigungen bietet Java die `if`- und `if-else`-Anweisung sowie die `switch`-Anweisung.

### 6.2.1 Die if-Anweisung

#### Syntax

    if (ausdruck)
      anweisung;

oder

    if (ausdruck)
      anweisung1;
    else
      anweisung2;

#### Bedeutung

Die `if`-Anweisung wertet zunächst den Ausdruck `ausdruck` aus. Danach führt sie die Anweisung `anweisung` genau dann aus, wenn das Ergebnis des Ausdrucks `true` ist. Ist `ausdruck` hingegen `false`, so wird die Anweisung nicht ausgeführt, sondern mit der ersten Anweisung nach der `if`-Anweisung fortgefahren.

Mit der `if-else`-Anweisung gibt es eine weitere Verzweigung in Java. Falls `ausdruck` wahr ist, wird `anweisung1` ausgeführt, andernfalls `anweisung2`. Eine der beiden Anweisungen wird also in jedem Fall ausgeführt.

Anstelle einer einzelnen Anweisung kann jeweils auch eine Folge von Anweisungen angegeben werden, wenn sie innerhalb eines Blocks steht. Dieser wird als Einheit betrachtet und komplett ausgeführt, wenn die entsprechende Bedingung zutrifft.

|  | Zu beachten ist, daß der Testausdruck in der Schleife vom Typ `boolean` sein muß. Anders als in C ist es in Java nicht erlaubt, einen numerischen Ausdruck an seiner Stelle zu verwenden. |  |
Hinweis

#### Dangling else

|  |  |  | Eine der Mehrdeutigkeiten, die in fast allen blockstrukturierten Programmiersprachen auftauchen können, wurde auch von den Java-Entwicklern nicht beseitigt. Als Beispiel wollen wir uns das folgende Codefragment ansehen, das leider nicht so ausgeführt wird, wie es die Einrückung erwarten läßt: |  |
Warnung

    001 if (a)
    002   if (b)
    003     s1;
    004 else
    005   s2;

Listing 6.2: Dangling else

Der `else`-Zweig gehört zu der innersten Verzweigung `if (b)...`, und die korrekte Einrückung würde lauten:

    001 if (a)
    002   if (b)
    003     s1;
    004   else
    005     s2;

Listing 6.3: Dangling else, ausgeschaltet

Dieses Problem ist in der Literatur unter dem Namen dangling else bekannt und kann nur auftauchen, wenn eine `if`- und eine `if-else`-Verzweigung ineinander geschachtelt werden und beide Anweisungen nicht durch Blockklammern begrenzt wurden. Um die Mehrdeutigkeit zu beseitigen, wird in Java wie auch in C oder C++ ein »freies« `else` immer an das am weitesten innen liegende `if` angehängt.

#### Bedingtes Kompilieren

|  |  |  | Eine weitere Besonderheit der Verzweigungen in Java rührt daher, daß die Sprache keinen Präprozessor besitzt und deshalb kein `#ifdef` kennt. Um eine eingeschränkte Form der bedingten Kompilierung zu verwirklichen, wird in Java das folgende Programmfragment in der Weise kompiliert, daß die Anweisung `anweisung` nicht mitübersetzt wird, da der Testausdruck konstant `false` ist:
    001 if (false)
    002   anweisung;
Listing 6.4: Bedingtes Kompilieren |  |
Tip

Allerdings sollte man hinzufügen, daß ein solches Verhalten in der Sprachspezifikation zwar dringend empfohlen wird, für die Compiler-Bauer aber nicht zwangsläufig verpflichtend ist.

Das hier beschriebene Verhalten eines Java-Compilers steht im Widerspruch zu einer anderen Forderung, nämlich der, nur erreichbare Anweisungen zu akzeptieren. Gemäß Sprachspezifikation soll der Compiler alle Anweisungen, die nicht erreichbar sind, ablehnen, also einen Fehler melden.

Nicht erreichbar im technischen Sinne sind dabei Anweisungen in Schleifen, deren Testausdruck zur Compile-Zeit `false` ist, und Anweisungen, die hinter einer `break`-, `continue`-, `throw`- oder `return`-Anweisung liegen, die unbedingt angesprungen wird. Die einzige Ausnahme von dieser Regel ist die im vorigen Absatz erwähnte Variante der konstant unwahren Verzweigung, die zur bedingten Kompilierung verwendet werden kann.

### 6.2.2 Die switch-Anweisung

#### Syntax

    switch (ausdruck)
    {
      case constant:
        anweisung;
      ...
      default:
    }

#### Bedeutung

Die `switch`-Anweisung ist eine Mehrfachverzweigung. Zunächst wird der Ausdruck `ausdruck`, der vom Typ `byte`, `short`, `char` oder `int` sein muß, ausgewertet. In Abhängigkeit vom Ergebnis wird dann die Sprungmarke angesprungen, deren Konstante mit dem Ergebnis des Ausdrucks übereinstimmt. Die Konstante und der Ausdruck müssen dabei zuweisungskompatibel sein.

Das optionale `default`-Label wird dann angesprungen, wenn keine passende Sprungmarke gefunden wird. Ist kein `default`-Label vorhanden und wird auch keine passende Sprungmarke gefunden, so wird keine der Anweisungen innerhalb der `switch`-Anweisung ausgeführt. Jede Konstante eines `case`-Labels darf nur einmal auftauchen. Das `default`-Label darf maximal einmal verwendet werden.

|  |  |  | Nachdem ein `case`- oder `default`-Label angesprungen wurde, werden alle dahinterstehenden Anweisungen ausgeführt. Im Gegensatz zu Sprachen wie PASCAL erfolgt auch dann keine Unterbrechung, wenn das nächste Label erreicht wird. Wenn dies erwünscht ist, muß der Kontrollfluß wie in C und C++ mit Hilfe einer `break`-Anweisung unterbrochen werden. Jedes `break` innerhalb einer `switch`-Anweisung führt dazu, daß zum Ende der `switch`-Anweisung verzweigt wird. |  |
Warnung

Wie aus den bisherigen Ausführungen deutlich wurde, ist die Semantik der `switch`-Anweisung in Java der in C und C++ sehr ähnlich. Ein wichtiger Unterschied besteht darin, daß in Java alle Anweisungen, die unmittelbar innerhalb des `switch` liegen, `case`- oder `default`-Labels sein müssen. Der Trick, in `switch`-Anweisungen Schleifen zu packen, die sich über mehrere Labels erstrecken, funktioniert in Java nicht. Die Sprachspezifikation erläutert dies am Beispiel von Duff's Device, das so in Java nicht kompilierbar ist:

    001 int q = (n+7)/8;
    002 switch (n%8) {
    003 case 0: do { foo();
    004 case 1:      foo();
    005 case 2:      foo();
    006 case 3:      foo();
    007 case 4:      foo();
    008 case 5:      foo();
    009 case 6:      foo();
    010 case 7:      foo();
    011         } while (--q >= 0);
    012 }

Listing 6.5: Duff's Device

Glücklicherweise ist derartiger Code mehr zur Verwirrung ahnungsloser Programmierer gedacht als zur ernsthaften Anwendung und kommt in der Praxis normalerweise kaum vor.

Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage, Addison Wesley, Version 3.0
<< | < | > | >> | API | © 1998-2002 Guido Krüger, http://www.javabuch.de