26.7 Anweisungen
Zu den Einrückungen von Anweisungen, insbesondere den Kontrollstrukturen, wurde schon weiter vorn in diesem Kapitel etwas gesagt. Wir wollen an dieser Stelle auf die einzelnen Elemente eingehen.
26.7.1 Schleifen
Der Einsatz der Schleifen hängt natürlich von ihrem Verwendungszweck ab. for-Schleifen sollten immer dann benutzt werden, wenn eine Variable um eine konstante Größe erhöht wird. Tritt in der Schleife keine Schleifenvariable auf, die inkrementiert oder dekrementiert wird, sollte eine while-Schleife genutzt werden. Eine do/while-Schleife sollte dann ihren Einsatz finden, wenn die Abbruchbedingung erst am Ende eines Schleifendurchlaufs ausgewertet werden kann. Variablen, die eine Größe oder Länge bezeichnen, können beim Durchlauf unrealistischerweise negative Werte annehmen. Leider können in Java keine Typen ohne Vorzeichen deklariert werden - lassen wir char einmal außen vor -, so wie in C für viele Datentypen unsigned erlaubt ist.
Für Bereichsangaben der Form a>=23 && a<=42 ist es empfehlenswert, den unteren Wert mit in den Vergleich einzubeziehen, den Wert für die obere Grenze jedoch nicht (inklusive untere Grenzen und exklusive obere Grenzen). Für unser Beispiel, in dem a im Intervall bleiben soll, ist Folgendes besser: a>=23 && a<43. Die Begründung dafür ist einleuchtend:
|
Die Größe des Intervalls ist die Differenz aus den Grenzen. |
|
Ist das Intervall leer, so sind die Intervallgrenzen gleich. |
|
Die untere Grenze ist nie größer als die obere Grenze. |
Die Standardbibliothek verwendet diese Konvention auch durchgängig bei substring(), subList() oder Array-Indexwerten.
Die Vorschläge können für normale Schleifen mit Vergleichen übernommen werden. So ist eine Schleife mit zehn Durchgängen besser in der Form
for ( a = 0; a < 10; a++ )
formuliert als in der semantisch äquivalenten Form
for ( a = 0; a <= 9; a++ )
Das Schlüsselwort continue
Wir können unsere Programme lesbarer machen, indem wir auf continue verzichten. Außerdem können wir ein break benutzen, anstatt mit Flags aus einer Schleife vorzeitig auszubrechen. Dazu zwei Beispiele. Folgendes ist zu vermeiden:
boolean endFlag = false;
do
{
if ( Bedingung )
{
// Code ohne Ende
endFlag = true;
}
} while ( weitereBedingung && !endFlag );
Stattdessen schreiben wir:
do
{
if ( Bedingung )
{
// Code wieder ohne Ende
break;
}
} while ( weitereBedingung );
Die alternative Lösung macht natürlich einen Unterschied, falls nach dem if noch Anweisungen in der Schleife stehen.
Ein continue am Ende einer if-Abfrage kann durch einen else-Teil bedeutend klarer gefasst werden. Zunächst das schlechte Beispiel:
while ( Bedingung ) // Durch continue verzuckert
{
if ( NochNeBedingung )
{
// Code,Code, code
continue;
}
// Weiterer schöner Code
}
Viel deutlicher ist:
while ( Bedingung )
{
if ( NochNeBedingung )
{
// Code, Code, Code
}
else
{
// Weiterer schöner Code
}
}
26.7.2 Switch, case und Durchfallen
Es ist eine Eigenschaft der case-Zweige einer switch-Anweisung, dass ein Zweig, der nicht durch ein break abgeschlossen ist, im nächsten case-Zweig weiter ausgeführt wird. Dies ist eine große Fehlerquelle. Wir betrachten wieder ein Beispiel:
switch ( Tag )
{
case A:
// Code, der durchfällt
case B:
lieblingsFunktion();
// und noch Code dazu
break; // jetzt erst switch-Anweisung verlassen
case C:
}
Günstiger ist es, die absichtlich durchfallenden case-Zweige kenntlich zu machen, beispielsweise so:
switch ( Tag )
{
case A:
// Code, der durchfällt
// FALLTHROUGH FALLTHROUGH
case B:
lieblingsFunktion();
// und noch Code dazu
break; // jetzt erst switch-Anweisung verlassen
case C:
}
|