Titel | Inhalt | Suchen | Index | API | Go To Java 2, Zweite Auflage, Handbuch der Java-Programmierung |
<< | < | > | >> | Kapitel 6 - Anweisungen |
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.
if (ausdruck) anweisung; |
oder
if (ausdruck) anweisung1; else anweisung2; |
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. |
|
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: |
|
001 if (a) 002 if (b) 003 s1; 004 else 005 s2; |
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; |
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.
Eine weitere Besonderheit der Verzweigungen in Java rührt daher, daß die Sprache keinen Präprozessor besitzt und daher 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:
|
|
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.
switch (ausdruck) { case constant: anweisung; ... default: } |
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. |
|
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 (%n8) { 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 } |
Glücklicherweise ist derartiger Code auch mehr zur Verwirrung ahnungsloser Programmierer geeignet als zur ernsthaften Anwendung und kommt in der Praxis normalerweise kaum vor.
Titel | Inhalt | Suchen | Index | API | Go To Java 2, Zweite Auflage, Addison Wesley, Version 2.0 |
<< | < | > | >> | © 2000 Guido Krüger, http://www.gkrueger.com |