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

7.3 Schleifen



Java besitzt die drei üblichen Schleifenanweisungen prozeduraler Programmiersprachen: eine nichtabweisende, eine abweisende und eine Zählschleife. Die Syntax und Semantik der Schleifen ist fast vollständig identisch zu den entsprechenden Anweisungen in C.

7.3.1 Die while-Schleife

Syntax

while (ausdruck)
  anweisung;

Bedeutung

Zuerst wird der Testausdruck, der vom Typ boolean sein muss, geprüft. Ist er true, wird die Anweisung ausgeführt, andernfalls wird mit der ersten Anweisung hinter der Schleife weitergemacht. Nachdem die Anweisung ausgeführt wurde, wird der Testausdruck erneut geprüft usw. Die Schleife wird beendet, sobald der Test false ergibt.

7.3.2 Die do-Schleife

Syntax

do
  anweisung;
while (ausdruck);

Bedeutung

Die do-Schleife arbeitet nichtabweisend, d.h. sie wird mindestens einmal ausgeführt. Da zunächst die Schleifenanweisung ausgeführt und erst dann der Testausdruck überprüft wird, kann die do-Schleife frühestens nach einem Durchlauf regulär beendet werden. Die Bearbeitung der Schleife wird immer dann beendet, wenn der Test des Schleifenausdrucks false ergibt.

7.3.3 Die for-Schleife

Syntax

for (init; test; update)
  anweisung;

Bedeutung

Der Kopf der for-Schleife besteht aus drei Ausdrücken, die jeder für sich optional sind:

break und continue

In Java gibt es zwei weitere Möglichkeiten, die normale Auswertungsreihenfolge in einer Schleife zu verändern. Taucht innerhalb einer Schleife eine break-Anweisung auf, wird die Schleife verlassen und das Programm mit der ersten Anweisung nach der Schleife fortgesetzt. Taucht dagegen eine continue-Anweisung auf, springt das Programm an das Ende des Schleifenrumpfs und beginnt mit der nächsten Iteration.

In der einfachsten Form arbeiten break und continue genauso wie in C und C++. Beide Anweisungen können innerhalb von do-, while- und for-Schleifen verwendet werden. Befindet sich ein break innerhalb einer mehrfach geschachtelten Schleife, so verlässt es die innerste Schleife. Dies gilt analog für continue. Neben dieser einfachen Form von break und continue gibt es in Java noch die mit einem Label versehene Form:

break Label;

continue Label;

Zu jedem mit einem Label versehenen break oder continue muss es eine mit einem Label versehene Kontrollstruktur geben, die diese Anweisung umschließt. Oft wird ein mit einem Label versehenes break verwendet, um zwei oder mehr ineinander geschachtelte Schleifen zu beenden:

001 /* Listing0706.java */
002 
003 public class Listing0706
004 {
005   public static void main(String[] args)
006   {
007     int[][] data = new int[10][10];
008 
009     //Multiplikationstafel erstellen
010     for (int i = 1; i <= 10; ++i) {
011       for (int j = 1; j <= 10; ++j) {
012         data[i - 1][j - 1] = i * j;
013       }
014     }
015 
016     //Produkt größer 43 suchen 
017   loop1:
018     for (int i = 1; i <= 10; ++i) {
019       for (int j = 1; j <= 10; ++j) {
020         if (data[i - 1][j - 1] > 43) {
021           System.out.println(i + "*" + j + "=" + (i*j));
022           break loop1;
023         }
024       } 
025     } 
026   }
027 }
Listing0706.java
Listing 7.6: Das gelabelte break

Das Programm erstellt zunächst eine Multiplikationstafel für die Zahlen von 1 bis 10. Ab Zeile 016 sucht es dann in einer geschachtelten Schleife nach den ersten beiden Faktoren, deren Produkt 43 übersteigt. Die äußere der beiden Schleifen hat das Label loop1, die innere ist ohne Label. Wenn die Anweisung break loop1; ausgeführt wird, springt das Programm an das Ende des mit dem Label loop1 markierten Anweisungsblocks, also hinter die geschweifte Klammer in Zeile 025. Hätten wir ein ungelabeltes break verwendet, wäre das Programm lediglich bis an das Ende von Zeile 024 gesprungen und die äußere Schleife hätte eine weitere Iteration durchgeführt.

Vollkommen analog zu der mit einem Label versehenen break-Anweisung kann auch die mit einem Label versehene Form der continue-Anweisung verwendet werden, um die nächste Iteration einer weiter außen liegenden Schleife einzuleiten.

Die break- und continue-Anweisungen, insbesondere die mit einem Label versehenen, stellen Sprunganweisungen dar. Im Vergleich zu den goto-Anweisungen anderer Programmiersprachen sind ihre Fähigkeiten aber auf kontrollierte Sprünge in Schleifenanweisungen beschränkt. Eine allgemeine Sprunganweisung gibt es in Java nicht (die Sprachdesigner haben sich aber scheinbar ein Hintertürchen offengelassen und goto zu einem reservierten Wort erklärt).

 Hinweis 

Die Bedeutung von gelabelten break- und continue-Anweisungen ist in der Praxis nicht so groß, wie man vermuten könnte. Unbedacht eingesetzt, können sie die Lesbarkeit eines Programms sogar vermindern. Eine weitere nützliche Anwendung des gelabelten break besteht darin, eine Schleife aus einer darin liegenden switch-Anweisung zu verlassen.

Die erweiterte for-Schleife

Mit Java 5 wurde die for-Schleife um eine syntaktische Variante erweitert, die den Umgang mit listenartigen Datenstrukturen, wie Collections und Arrays, vereinfacht. Diese, auch als »foreach« bezeichnete Variante wird erst nach der Behandlung von Objekten (Kapitel 8 bis Kapitel 11) und der Einführung von Collections (Kapitel 15 und Kapitel 16) voll verständlich. Aus Gründen der Systematik soll sie trotzdem an dieser Stelle erläutert werden; der Abschnitt kann aber beim ersten Lesen übersprungen werden.

Die erweiterte for-Schleife hat folgende Syntax:

for (formalerparameter : ausdruck)
  anweisung;

»formalerparameter« ist dabei eine aus Datentyp und Variablenname bestehende Parameterdeklaration der Art Integer i oder Object o und »ausdruck« ist eine Instanz oder ein Ausdruck des Typs java.lang.Iterable oder ein Array. Angewendet auf eine Collection hat die erweiterte for-Schleife dieselbe Bedeutung wie folgendes Codestück:

for (Iterator it = ausdruck.iterator(); it.hasNext(); ) {
  formalerparameter = it.next();
  anweisung
}

Ein einfaches Beispiel zeigt die Anwendung in der Praxis:

001 public static void printVector1(Vector v)
002 {
003   for (Iterator it = v.iterator(); it.hasNext(); ) {
004     Object o = it.next();
005     System.out.println(o);
006   }
007 }
008 
009 public static void printVector2(Vector v)
010 {
011   for (Object o : v) {
012     System.out.println(o);
013   }
014 }
Listing 7.7: Anwendung der erweiterten for-Schleife auf Collections

In printVector1 wird eine konventionelle for-Schleife verwendet, um die Elemente des Vectors auf der Konsole auszugeben. Dazu wird zunächst ein Iterator deklariert, am Anfang der Schleife initialisiert und bei jedem Schleifendurchlauf darauf zugegriffen. Das ist etwas umständlich und syntaktisch nicht sehr elegant. Die Methode printVector2 verwendet dagegen die erweiterte for-Schleife und kann völlig auf die explizite Deklaration und Verwendung des Iterators verzichten. Sie hat die gleiche Bedeutung wie die erste Variante. Der Code ist nun einfacher zu lesen und intuitiv zu verstehen (der Doppelpunkt in der Schleifendeklaration wird wie »in« gelesen).

Die erweiterte for-Schleife lässt sich auch auf Arrays anwenden. Sie ist dann eine Kurzform für folgendes Codestück:

Typ[] a = ausdruck;
for (int i = 0; i < a.length; i++) {
  formalerparameter = a[i];
  statement
}

Dass dies ähnlich nützlich ist wie die Anwendung auf Collections, zeigt folgendes Beispiel:

001 public static void printArray1(int[] args)
002 {
003   // Ausgabe aller Elemente des Arrays über den Index
004   for (int i = 0; i < args.length; ++i) {
005     System.out.println(args[i]);
006   }
007 }
008 
009 public static void printArray2(int[] args)
010 {
011   // Ausgabe aller Elemente des Arrays über die erweiterte
012   // for-Schleife (gelesen: für all a im Array args)
013   for (int a : args) {
014     System.out.println(a);
015   }
016 }
Listing 7.8: Anwendung der erweiterten for-Schleife auf Arrays

So wird der Code einfacher und klarer.

Die erweiterte for-Schleife wurde nicht entwickelt, um alle Spezialfälle eines Collection- oder Array-Durchlaufs abzubilden. Sie will lediglich den vermutlich häufigsten Fall vereinfachen, nämlich das einmalige Durchlaufen aller Elemente von vorne nach hinten. Für Sonderfälle ist nach wie vor die konventionelle for-Schleife zuständig. Zu diesen zählen beispielsweise:

  • Das Durchlaufen der Collection von hinten nach vorn
  • Das simultane Durchlaufen mehrerer Collections
  • Das Löschen oder Ändern einzelner Elemente während des Durchlaufs
 Hinweis 


 Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage, Addison Wesley, Version 7.0
 <<    <     >    >>   API  © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de