Programmieren in Java: Einführung


Kapitel 8: Kontrollstrukturen


Inhaltsverzeichnis

Dieses Buch ist unter einer Creative Commons-Lizenz lizensiert.


8.1 Allgemeines

Code verzweigen und wiederholen

In all den vorherigen Kapiteln haben Sie bereits viele wichtige Dinge kennengelernt, wenn es darum geht, Anwendungen in Java zu entwickeln. Bisher sind Ihre Programme jedoch mehr oder weniger direkt beim Laden linear ausgeführt worden. Das heißt, die von Ihnen angegebenen Anweisungen wurden immer vollständig und genau ein einziges Mal ausgeführt. Mit all den bisher kennengelernten Sprachfunktionen von Java ist es uns bisher noch nicht möglich, abhängig von einer bestimmten Bedingung unterschiedlichen Code auszuführen - die Programmausführung also zu verzweigen. Ebenfalls steht uns noch keine Möglichkeit zur Verfügung, die Ausführung von Code mehrmals ablaufen zu lassen - also Code zu wiederholen. Die dazu notwendigen Kontrollstrukturen lernen Sie nun in diesem Kapitel kennen.


8.2 if-Anweisung

Rechts oder links

Verzweigungen werden in Java wie auch in C# und C++ mit dem Schlüsselwort if implementiert. Eine Verzweigung ermöglicht eine Code-Ausführung in Abhängigkeit einer Bedingung. Der schematische Aufbau einer Verzweigung sieht wie folgt aus.

if (BEDINGUNG) 
{ 
  ANWEISUNGSBLOCK 
} 

Zuerst geben Sie immer das Schlüsselwort if an. Hinter dem Schlüsselwort folgt eine runde Klammer. Innerhalb dieser Klammer muss eine Bedingung überprüft werden. Häufig kommt hier ein Vergleichsoperator zum Einsatz. So kann hier beispielsweise überprüft werden, ob eine Variable größer als eine andere ist. Wichtig ist, dass das Ergebnis der Operation in den runden Klammern einen Wahrheitswert liefert. Ist das Ergebnis true, dann und nur dann wird der Anweisungsblock hinter der runden Klammer ausgeführt.

Im Anweisungsblock können beliebig viele Anweisungen stehen. Sie werden alle durch die beiden geschweiften Klammern eingegrenzt. Wenn also die zu überprüfende Bedingung true ergibt, dann wird der Anweisungsblock mit all seinen Befehlen ausgeführt. Ist die zu überprüfende Bedingung jedoch false, wird der Anweisungsblock ignoriert und übersprungen. In diesem Fall setzt die Programmausführung hinter der geschlossenen geschweiften Klammer des Anweisungsblocks fort.

Sehen Sie sich folgendes Beispiel an, um den Einsatz einer if-Kontrollstruktur in der Praxis nachzuvollziehen.

import java.applet.*; 
import java.awt.*; 
import java.awt.event.*; 

public class MyApplet extends Applet implements KeyListener 
{ 
  TextField Input; 

  public void init() 
  { 
    Input = new TextField(10); 
    Input.addKeyListener(this); 
    add(Input); 
  } 

  public void keyReleased(KeyEvent ev) 
  { 
    if (ev.getKeyCode() == KeyEvent.VK_ENTER) 
    { 
      Input.setText(""); 
    } 
  } 

  public void keyTyped(KeyEvent ev) { } 
  public void keyPressed(KeyEvent ev) { } 
} 

Das Beispiel besteht aus einer Klasse, die von java.applets.Applet abgeleitet ist und außerdem das Interface java.awt.event.KeyListener implementiert. Es handelt sich also wieder um ein vollwertiges Java-Applet, das durch das Interface gezwungen wird, die Methoden keyReleased(), keyTyped() und keyPressed() zu implementieren. Diese drei Methoden sind notwendig, wenn auf Tastatureingaben reagiert werden soll: keyReleased() wird aufgerufen, wenn eine Taste losgelassen wird. keyTyped() wird aufgerufen, wenn eine Taste gedrückt wird. Und keyPressed() wird aufgerufen, wenn eine Taste gedrückt und wieder losgelassen wird. Während die Methode keyReleased() ein paar Anweisungen enthält, bestehen keyTyped() und keyPressed() im Beispiel aus leeren Anweisungsblöcken.

Das Java-Applet bedient sich einer Klasse aus dem Paket java.awt. Dieses Paket enthält Klassen, mit denen grafische Benutzeroberflächen erstellt werden können. Die im Applet verwendete Klasse java.awt.TextField stellt eine Eingabeschaltfläche in der Applet-Oberfläche grafisch dar. Diese Textbox wird innerhalb der Methode init() erstellt. Indem an den Konstruktor von java.awt.TextField der Wert 10 übergeben wird, wird das Textfeld automatisch so dimensioniert, dass es 10 Zeichen breit ist. Im Buch Programmieren in Java: Aufbau wird das Paket java.awt ausführlich vorgestellt.

Nachdem das Textfeld mit new erstellt wurde, wird ein Objekt als Empfänger registriert, das bei Tastatureingaben in das Textfeld informiert werden soll. Das Objekt, das als Empfänger der Tastatureingaben dienen soll, ist this - also das Objekt, das der Browser automatisch basierend auf der Klasse MyApplet erstellt. Daher wird das Schlüsselwort this an die Methode addKeyListener() übergeben. Aus dieser Code-Zeile ergibt sich zwangsläufig, dass die Klasse MyApplet nun das Interface KeyListener implementieren muss. Denn der Parameter, der an addKeyListener() übergeben wird, kann zwar auf einer beliebigen Klasse basieren, diese muss jedoch das Interface java.awt.event.KeyListener implementieren. Daraus folgt wiederum, dass die drei Methoden aus dem Interface java.awt.event.KeyListener in der Klasse MyApplet definiert werden müssen.

Die letzte Code-Zeile in der Methode init() fügt nun das Textfeld tatsächlich in die Oberfläche des Java-Applets ein. Alle Operationen sind bisher im Verborgenen abgelaufen, also lediglich im Speicher des Computers. Erst mit dem Aufruf von add() wird das übergebene grafische Element - in diesem Fall also das Textfeld - im Java-Applet selber angezeigt.

Nachdem das Textfeld im Applet eingeblendet wird, kann der Anwender beliebige Zeichen eingeben. Jedesmal, wenn er eine Taste drückt und loslässt, werden die Methoden keyTyped(), keyReleased() und keyPressed() aufgerufen. Da lediglich die Methode keyReleased() sinnvolle Anweisungen enthält, geschieht in den anderen beiden Methoden nichts.

Innerhalb von keyReleased() ist nun eine if-Kontrollstruktur angegeben. In den runden Klammern hinter if wird mit dem Vergleichsoperator == eine Bedingung überprüft. Nur wenn diese Bedingung wahr ist, wird der darauffolgende Anweisungsblock ausgeführt. Andernfalls wird er übersprungen. Nachdem die Methode keyReleased() außer der if-Kontrollstruktur keine weiteren Anweisungen mehr enthält, würde bei einem Ergebnis von false bei der Überprüfung der Bedingung auch nichts passieren.

Was wird im obigen Beispiel genau für eine Bedingung überprüft? Den drei Methoden aus dem Interface java.awt.event.KeyListener wird jeweils ein Parameter vom Typ KeyEvent mitgegeben. Anhand dieses Parameters kann innerhalb der Methode herausgefunden werden, welche Taste denn eigentlich genau gedrückt oder losgelassen wurde. Dazu bietet die Klasse KeyEvent unter anderem eine Methode getKeyCode() an, die einen Wert zurückgibt, der eine bestimmte Taste repräsentiert. Außerdem sind in der Klasse KeyEvent eine Reihe öffentlicher und statischer Eigenschaften definiert, die ebenfalls alle eine ganz bestimmte Taste repräsentieren. So steht beispielsweise die Eigenschaft VK_ENTER für die Taste Enter.

Indem nun in den runden Klammern von if der Rückgabewert von getKeyCode() mit VK_ENTER auf Gleichheit überprüft wird, wird überprüft, ob der Anwender ganz einfach Enter gedrückt hat. Ist dies der Fall, dann ist die Bedingung true - andernfalls false. Nur wenn die Bedingung true ergibt, wird der nachfolgende Anweisungsblock ausgeführt. Das heißt, nur wenn der Anwender Enter gedrückt hat, wird der Anweisungsblock ausgeführt.

Innerhalb des Anweisungsblocks von if wird die Methode setText() für die Textbox aufgerufen. Über diese Methode kann das Textfeld auf einen bestimmten Wert gesetzt werden. Indem der Methode eine leere Zeichenkette übergeben wird, wird das Textfeld ganz einfach gelöscht. Das bedeutet insgesamt, dass das Textfeld dann gelöscht wird, wenn der Anwender Enter drückt. Nur in diesem Fall ist die Bedingung wahr, nur in diesem Fall wird das Textfeld auf einen leeren Wert gesetzt.

Obiges Programm wird um wenige Zeilen geändert, so dass es nun wie folgt aussieht.

import java.applet.*; 
import java.awt.*; 
import java.awt.event.*; 

public class MyApplet extends Applet implements KeyListener 
{ 
  TextField Input; 

  public void init() 
  { 
    Input = new TextField(10); 
    Input.addKeyListener(this); 
    add(Input); 
  } 

  public void keyReleased(KeyEvent ev) 
  { 
    if (ev.getKeyCode() == KeyEvent.VK_ENTER) 
    { 
      Input.setForeground(Color.red); 
    } 
    else 
    { 
      Input.setForeground(Color.blue); 
    } 
  } 

  public void keyTyped(KeyEvent ev) { } 
  public void keyPressed(KeyEvent ev) { } 
} 

Innerhalb des if-Anweisungsblocks wird nicht mehr das Textfeld mit setText() gelöscht. Stattdessen wird mit setForeground() die Textfarbe auf Rot gesetzt.

Die if-Kontrollstruktur ist nun außerdem um einen else-Teil erweitert worden. Dazu wurde das Schlüsselwort else hinter den if-Anweisungsblock gestellt. Dem else folgt außerdem wieder ein eigener Anweisungsblock. In diesem else-Anweisungsblock wird ebenfalls mit setForeground() die Textfarbe gesetzt - jedoch diesmal nicht auf Rot, sondern auf Blau.

Was passiert nun in diesem Programm? Wenn der Anwender Enter drückt und loslässt, wird die Textfarbe daraufhin auf Rot gesetzt. In allen anderen Fällen - wenn er also beliebige Buchstaben eingibt - wird die Textfarbe auf Blau gesetzt. Während der Anweisungsblock nach dem if nur dann ausgeführt wird, wenn die zu überprüfende Bedingung true ergibt, wird der Anweisungsblock nach dem else dann ausgeführt, wenn die zu überprüfende Bedingung false ergibt.

Die schematische Darstellung der if-else-Kontrollstruktur sieht wie folgt aus.

if (BEDINGUNG) 
{ 
  ANWEISUNGSBLOCK 
} 
else 
{ 
  ANWEISUNGSBLOCK 
} 

Sie können also jede if-Kontrollstruktur zu einer if-else-Kontrollstruktur erweitern, müssen aber nicht. Der else-Anweisungsblock kann jederzeit weggelassen werden.

Eine if-Anweisung kann neben if- und else-Anweisungsblöcken auch else-if-Anweisungsblöcke enthalten. Sehen Sie sich folgendes Beispiel an.

import java.applet.*; 
import java.awt.*; 
import java.awt.event.*; 

public class MyApplet extends Applet implements KeyListener 
{ 
  TextField Input; 

  public void init() 
  { 
    Input = new TextField(10); 
    Input.addKeyListener(this); 
    add(Input); 
  } 

  public void keyReleased(KeyEvent ev) 
  { 
    if (ev.getKeyCode() == KeyEvent.VK_ENTER) 
    { 
      Input.setForeground(Color.red); 
    } 
    else if (ev.getKeyCode() == KeyEvent.VK_TAB) 
    { 
      Input.setForeground(Color.green); 
    } 
    else if (ev.getKeyCode() == KeyEvent.VK_CAPS_LOCK) 
    { 
      Input.setForeground(Color.yellow); 
    } 
    else 
    { 
      Input.setForeground(Color.blue); 
    } 
  } 

  public void keyTyped(KeyEvent ev) { } 
  public void keyPressed(KeyEvent ev) { } 
} 

Die if-Kontrollstruktur arbeitet nun wie folgt: Es wird zuerst überprüft, ob der Anwender Enter gedrückt hat. Ist dies nicht der Fall und die erste Bedingung daher false, wird die Bedingung hinter dem ersten else if überprüft. In diesem Fall wird der Rückgabewert von getKeyCode() mit KeyEvent.VK_TAB verglichen - es wird überprüft, ob der Anwender die Tabulator-Taste gedrückt hat. Ist dies nicht der Fall, wird die nächste Bedingung hinter dem nächsten else if überprüft. Hier wird nun getestet, ob der Anwender die Caps-Lock-Taste gedrückt hat. Wenn das auch nicht true ergibt, dann erst wird der Anweisungsblock hinter else ausgeführt.

Mit else if-Zweigen ist es also möglich, mehrere Bedingungen zu überprüfen. Die Programmausführung prüft hierbei die Bedingungen in der Reihenfolge, in der sie im Code angegeben sind. Wenn eine Bedingung wahr ist, finden keine nachfolgenden else if-Überprüfungen mehr statt. Stattdessen wird der betreffende Anweisungsblock ausgeführt. Trifft überhaupt keine Bedingung zu, wird der Anweisungsblock hinter else ausgeführt.

Die schematische Darstellung einer if-Kontrollstruktur sieht also komplett wie folgt aus.

if (BEDINGUNG) 
{ 
  ANWEISUNGSBLOCK 
} 
else if (BEDINGUNG) 
{ 
  ANWEISUNGSBLOCK 
} 
else 
{ 
  ANWEISUNGSBLOCK 
} 

Eine if-Kontrollstruktur beginnt immer mit dem Schlüsselwort if. Hinter dem if-Anweisungsblock können beliebig viele else if-Überprüfungen stattfinden. Hinter den else if-Anweisungsblöcken kann ganz am Ende der if-Kontrollstruktur ein else-Anweisungsblock folgen. Sowohl die else if-Überprüfungen als auch der else-Anweisungsblock sind optional.


8.3 switch-Anweisung

Spezielle if-Anweisung

Das vorherige Beispiel lässt sich mit Hilfe einer switch-Anweisung auch wie folgt schreiben.

import java.applet.*; 
import java.awt.*; 
import java.awt.event.*; 

public class MyApplet extends Applet implements KeyListener 
{ 
  private TextField Input; 

  public void init() 
  { 
    Input = new TextField(10); 
    Input.addKeyListener(this); 
    add(Input); 
  } 

  public void keyReleased(KeyEvent ev) 
  { 
    switch (ev.getKeyCode()) 
    { 
      case KeyEvent.VK_ENTER: 
      { 
        Input.setForeground(Color.red); 
        break; 
      } 
      case KeyEvent.VK_TAB: 
      { 
        Input.setForeground(Color.green); 
        break; 
      } 
      case KeyEvent.VK_CAPS_LOCK: 
      { 
        Input.setForeground(Color.yellow); 
        break; 
      } 
      default: 
      { 
        Input.setForeground(Color.blue); 
        break; 
      } 
    } 
  } 

  public void keyTyped(KeyEvent ev) { } 
  public void keyPressed(KeyEvent ev) { } 
} 

Eine switch-Anweisung ist daher nur eine spezialisierte Form einer if-Anweisung. Eine switch-Anweisung kann dann verwendet werden, wenn die zu überprüfende Bedingung mit Variablen vom Datentyp char, byte, short oder int arbeitet und außerdem auf Gleichheit überprüft wird. In allen anderen Fällen - wenn Sie also beispielsweise mit Referenzvariablen arbeiten oder auf Ungleichheit überprüfen möchten - müssen Sie die if-Anweisung verwenden.

Der schematische Aufbau einer switch-Anweisung sieht wie folgt aus.

switch (AUSDRUCK) 
{ 
  case WERT: 
  { 
    ANWEISUNGSBLOCK 
    break; 
  } 
  case WERT: 
  { 
    ANWEISUNGSBLOCK 
    break; 
  } 
  default: 
  { 
    ANWEISUNGSBLOCK 
    break; 
  } 
} 

Hinter dem Schlüsselwort switch wird ein Ausdruck - beispielsweise eine Variable oder ein Rückgabewert einer Methode - in Klammern gesetzt, der überprüft werden soll. Wichtig ist, dass der Datentyp des Ausdrucks char, byte, short oder int ist.

Hinter dem Ausdruck folgen eine geöffnete und eine geschlossene geschweifte Klammer, zwischen denen die gesamte switch-Kontrollstruktur definiert wird. Innerhalb der switch-Anweisung werden verschiedene Zweige definiert, die jeweils mit dem Schlüsselwort case beginnen. Hinter case wird nun ein Wert angegeben, auf den hin der Ausdruck in Klammern überprüft werden soll. Hinter dem Wert wird außerdem ein Doppelpunkt angegeben, hinter dem wiederum ein neuer Anweisungsblock in geschweiften Klammern folgt.

Die switch-Anweisung arbeitet nun wie folgt: Schritt für Schritt werden die Werte, die hinter den case-Schlüsselwörtern angegeben sind, mit dem Ausdruck verglichen. Wenn ein Wert mit dem Ausdruck übereinstimmt, wird der entsprechende Anweisungsblock hinter case ausgeführt. In diesem Anweisungsblock können wie gewohnt beliebig viele Java-Anweisungen angegeben sein.

Ist der Anweisungsblock abgearbeitet worden und soll demnach die switch-Anweisung beendet werden, muss am Ende des Anweisungsblocks ein break stehen. Wenn dieses break nicht am Ende eines Anweisungsblocks gesetzt ist, wird das Programm mit dem nächsten Anweisungsblock innerhalb der switch-Kontrollstruktur fortfahren. Dies kann unter Umständen gewünscht sein, ist jedoch in den meisten Fällen ein Programmierfehler. Vergessen Sie also nicht, am Ende eines case-Anweisungsblocks ein break zu setzen, wenn die switch-Kontrollstruktur nur diesen einen Anweisungsblock abarbeiten soll, und danach das Programm hinter der switch-Anweisung fortsetzen soll.

Ein Zweig innerhalb einer switch-Kontrollstruktur darf mit dem Schlüsselwort default beginnen, hinter dem kein Wert, sondern nur der Doppelpunkt angegeben wird. Der Anweisungsblock hinter default wird dann ausgeführt, wenn keiner der hinter case angegebenen Werte mit dem Ausdruck übereinstimmt. Der default-Zweig entspricht also der else-Anweisung einer if-Kontrollstruktur und ist ebenfalls wie diese optional.


8.4 while-Schleife

Wiederholte Code-Ausführung

Während mit einer if- und switch-Kontrollstruktur unterschiedlicher Code in Abhängigkeit einer Bedingung ausgeführt werden kann, kann mit einer while-Schleife Code mehrmals ausgeführt werden. Sehen Sie sich dazu folgendes Beispiel an.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    int zaehler = 0; 
    int basis = 2; 
    int exponent = 3; 
    int ergebnis = 1; 

    while (zaehler++ < exponent) 
    { 
      ergebnis *= basis; 
    } 

    System.out.print(basis + " hoch " + exponent + " = " + ergebnis); 
  } 
} 

Obige Beispiel-Anwendung in Form einer Java-Application errechnet die Potenz zweier Zahlen. Die Werte der Variablen basis und exponent sollen derart verrechnet werden, dass basis so oft mit sich selber multipliziert wird wie in exponent angegeben. Um eine Wiederholung von Code-Anweisungen - in diesem Fall nämlich die der Multiplikation - zu ermöglichen, bietet Java die while-Schleife an.

Die while-Schleife ist so aufgebaut, dass zuerst das Schlüsselwort while angegeben wird und dahinter in Klammern eine Bedingung überprüft wird. Wie so häufig bei Überprüfungen von Bedingungen kommt auch im obigen Beispiel wieder ein Vergleichsoperator zum Einsatz: Es wird überprüft, ob die Variable zaehler kleiner als die Variable exponent ist. Die Variable zaehler wird außerdem mit dem Inkrement-Operator um 1 erhöht. Der Vergleich findet jedoch mit dem ursprünglichen Wert von zaehler statt, nachdem der Inkrement-Operator hinter dem Operanden angegeben ist.

Hinter dem Schlüsselwort while und der Bedingung in Klammern wird ein Anweisungsblock in geschweiften Klammern angegeben. In diesem Anweisungsblock können wie gewohnt beliebig viele Java-Befehle zusammengefasst werden.

Die while-Schleife funktioniert nun wie folgt: Wenn die zu überprüfende Bedingung wahr ist, wird der Anweisungsblock der Schleife ausgeführt. Ist die zu überprüfende Bedingung nicht wahr, wird der Anweisungsblock übersprungen, das Programm setzt dann die Code-Ausführung hinter der geschlossenen geschweiften Klammer des Anweisungsblocks fort. Wenn die Bedingung jedoch wahr ist und der Anweisungsblock ausgeführt wurde, dann - und das ist jetzt der entscheidende Unterschied zwischen while- und if-Kontrollstrukturen - wird die Bedingung erneut überprüft. Ist sie wieder wahr, wird der Anweisungsblock noch einmal ausgeführt. Das heißt, dass nach jedem Schleifendurchgang das Programm nicht hinter der Schleife fortsetzt, sondern die Bedingung neu überprüft und davon abhängig die Schleife eventuell nochmal neu ausführt.

Im Beispiel wird mit dem kombinierten Zuweisungsoperator *= die Variable ergebnis mit basis multipliziert und das Ergebnis wiederum in der Variablen ergebnis gespeichert. Indem dieser Anweisungsblock, also genaugenommen diese Multiplikation, so oft ausgeführt wird, bis die Variable zaehler nicht mehr kleiner als exponent ist, berechnet die Schleife die Potenz der beiden Werte in basis und exponent. Nachdem die Schleife beendet ist, wird mit System.out.print() abschließend das Ergebnis der Berechnung auf die Standardausgabe ausgegeben.

while (BEDINGUNG) 
{ 
} 

Oben sehen Sie die schematische Darstellung der while-Schleife.


8.5 do-while-Schleife

Schleife mit mindestens einem Durchlauf

Wie mit der while-Schleife kann auch mit der do-while-Schleife Code wiederholt ausgeführt werden. Der Unterschied ist: Die while-Schleife überprüft jeweils zu Beginn eines Schleifendurchgangs, ob eine Bedingung wahr ist oder nicht. Die do-while-Schleife überprüft die Bedingung jeweils am Ende eines Schleifendurchgangs. Das bedeutet, dass die do-while-Schleife immer mindestens einmal ausgeführt wird.

Das Code-Beispiel der while-Schleife wird im Folgenden umgeschrieben, so dass die do-while-Schleife verwendet wird.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    int zaehler = 0; 
    int basis = 2; 
    int exponent = 3; 
    int ergebnis = 1; 

    do 
    { 
      ergebnis *= basis; 
    } while (++zaehler < exponent); 

    System.out.print(basis + " hoch " + exponent + " = " + ergebnis); 
  } 
} 

Das Programm errechnet immer noch die Potenz der beiden Variablen basis und exponent. Wird die Variable exponent jedoch auf 0 gesetzt, gibt das Programm ein falsches Ergebnis aus. In diesem Fall wird nämlich die Schleife genau einmal ausgeführt und die Basis mit dem Wert 1 aus der Variablen ergebnis multipliziert. Es wird also für einen Exponenten 0 als Ergebnis nicht 1 ausgegeben, sondern die eingegebene Basis selber.

Beachten Sie, dass der Inkrement-Operator der Variablen zaehler nun außerdem vor dem Operanden steht und nicht mehr dahinter. Das heißt, für den Vergleich wird der um 1 erhöhte Wert herangezogen und mit der Variablen exponent verglichen. Die Umstellung des Operators ist notwendig, da die Überprüfung nun nicht mehr vor einem Schleifendurchgang stattfindet, sondern jeweils dahinter. Gehen Sie im Kopf schrittweise die Anweisungen durch, um zu sehen, dass der Code wie gewünscht funktioniert - mit Ausnahme für Exponenten gleich 0.


8.6 for-Schleife

Zähl-Schleife

Die for-Schleife wiederholt ähnlich wie die while- und do-while-Schleife mehrfach Code. Die spezielle Konstruktion der for-Schleife bietet eine Verwendung an, wenn bekannt ist, wie oft eine Schleife wiederholt werden muss.

Der schematische Aufbau der Schleife sieht wie folgt aus.

for (INITIALISIERUNG; BEDINGUNG; WERTÄNDERUNG) 
{ 
  ANWEISUNGSBLOCK 
} 

Die for-Schleife beginnt mit dem Schlüsselwort for, hinter dem eine große runde Klammer folgt. In dieser Klammer wird nicht wie in den anderen Schleifen lediglich eine Bedingung überprüft. Diese Klammer besteht hingegen aus drei Abschnitten, die durch Semikolon getrennt werden. Im ersten Abschnitt findet eine Initialisierung statt, im zweiten Abschnitt wird eine Bedingung überprüft, und im dritten Abschnitt wird ein Wert geändert.

Hinter der runden Klammer folgt zwischen zwei geschweiften Klammern wie üblich bei Schleifen der Anweisungsblock, der den Code enthält, der wiederholt werden muss.

Die for-Schleife arbeitet nun wie folgt: Trifft die Programmausführung auf die Schleife, wird zuerst der Code im Initialisierungsabschnitt ausgeführt. Hier wird normalerweise eine Variable auf einen bestimmten Wert gesetzt. Ist dies geschehen, wird im nächsten Abschnitt des Schleifenkopfs eine Bedingung überprüft. Ist diese Bedingung wahr, wird der Anweisungsblock ausgeführt. Andernfalls setzt die Programmausführung hinter der Schleife fort. Die Bedingung, die überprüft wird, bedient sich normalerweise der Variable, die im Initialisierungsabschnitt auf einen bestimmten Wert gesetzt wurde.

Wenn der Anweisungsblock der Schleife durchlaufen wurde, wird die Wertänderung im dritten Abschnitt des Schleifenkopfs ausgeführt. Hier wird sehr häufig der Inkrement- oder Dekrementoperator verwendet und auf die Variable angewandt, die auch im Initialisierungsabschnitt und in der zu überprüfenden Bedingung vorkommt. Diese Variable wird erhöht oder verringert.

Danach wird wiederum die Bedingung überprüft. Ist sie wahr, wird der Anweisungsblock erneut ausgeführt, andernfalls die Schleife beendet.

Die spezielle Konstruktion der for-Schleife sieht also so aus, dass die Initialisierung und die Änderung einer Variablen nun im Schleifenkopf vorgenommen wird. Wenn Sie die Initialisierung stattdessen vor der Schleife vornehmen und den Wert der Variablen direkt im Anweisungsblock ändern, können Sie eine for-Schleife auch als while- oder do-while-Schleife schreiben. Die Schleifen sind also genaugenommen beliebig austauschbar. Je nach Situation ist die eine oder andere Schleifenart vorzuziehen, um den Code lesbarer zu machen.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    int zaehler; 
    int basis = 2; 
    int exponent = 3; 
    int ergebnis = 1; 

    for (zaehler = 0; zaehler < exponent; ++zaehler) 
    { 
      ergebnis *= basis; 
    } 

    System.out.print(basis + " hoch " + exponent + " = " + ergebnis); 
  } 
} 

Im obigen Beispiel sehen Sie die Verwendung der for-Schleife in der Praxis. Die Variable zaehler, von der abhängt, wie oft die Schleife wiederholt werden muss, ist die Zählvariable. Sie wird mit 0 initialisiert und nach jedem Schleifendurchgang mit dem Inkrement-Operator um 1 erhöht. Wenn der Wert von zaehler nicht mehr kleiner als der Wert der Variablen exponent ist, wird die Schleife nicht mehr ausgeführt und beendet.


8.7 Kontrolltransferanweisungen

Schleifendurchgang und Schleifen beenden

Java bietet zwei Kontrolltransferanweisungen, mit denen ein Schleifendurchgang oder auch eine Schleife komplett abgebrochen werden kann. Die Kontrolltransferanweisungen heißen break und continue. Sie können ausschließlich in Schleifen verwendet werden, genauer im Anweisungsblock einer Schleife - mit der Ausnahme, dass break auch in der switch-Anweisung verwendet werden kann.

Wenn die Code-Ausführung auf ein break trifft, bedeutet dies, dass die Schleife sofort abgebrochen wird. Nach dem break fährt also die Programmausführung direkt hinter der Schleife fort.

Mit einem continue hingegen wird der aktuelle Schleifendurchgang abgebrochen. Das heißt, nach continue wird sofort die Schleifenbedingung erneut überprüft und davon abhängig dann die Scheife erneut durchlaufen oder nicht. Während bei break die Programmausführung hinter die Schleife springt, wird bei continue die Schleifenbedingung neu überprüft. Bei einer for-Schleife wird außerdem vor der Überprüfung der Bedingung die Wertänderung im Schleifenkopf vorgenommen.


8.8 Aufgaben

Übung macht den Meister

Sie können die Lösungen zu allen Aufgaben in diesem Buch als ZIP-Datei erwerben.

  1. Entwickeln Sie ein Java-Applet, das bei einem einfachen Mausklick die Hintergrundfarbe des Applets auf Blau setzt und bei einem doppelten Mausklick auf Rot. Lösen Sie die Aufgabe einmal unter Verwendung der if- und einmal unter Verwendung der switch-Kontrollstruktur. Um die Anzahl der Mausklicks herauszufinden, rufen Sie die Methode getClickCount() für das Objekt auf, das als einziger Parameter automatisch vom Java-System an die Methoden aus dem Interface java.awt.event.MouseListener übergeben wird. Die Methode getClickCount() besitzt einen Rückgabewert vom Typ int, der die Anzahl der Mausklicks angibt.

  2. Erweitern Sie Ihr in Aufgabe 1 entwickeltes Java-Applet dahingehend, dass die Hintergrundfarbe des Applets nur dann auf Blau oder Rot gesetzt wird, wenn zusätzlich zum einfachen oder doppelten Mausklick die STRG-Taste gedrückt gehalten wird.

  3. Entwickeln Sie eine Java-Application, die die Quersumme einer beliebigen Ganzzahl berechnet und auf die Standardausgabe ausgibt. So soll zum Beispiel für die Zahl 12345 die Quersumme 15 errechnet werden.

  4. Entwickeln Sie eine Java-Application, die die Ziffern einer beliebigen Ganzzahl umdreht und auf die Standardausgabe ausgibt. So wird zum Beispiel aus der Zahl 12345 die Zahl 54321.

  5. Entwickeln Sie ein Java-Applet, in das Sie mit java.awt.TextField ein Texteingabefeld setzen. Wenn der Anwender "Rot" in die Textbox tippt und Enter drückt, soll die Hintergrundfarbe des Applets auf Rot gesetzt werden. Um den Inhalt der Textbox zu erhalten, rufen Sie die Methode getText() für Objekte der Klasse java.awt.TextField auf. Diese Methode gibt den Inhalt der Textbox als Objekt vom Typ java.lang.String zurück. Sie können einen Vergleich zweier Objekte vom Typ java.lang.String durchführen, indem Sie für Objekte dieser Klasse die Methode equals() aufrufen und ihr einen Parameter vom Typ java.lang.String übergeben. equals() gibt true zurück, wenn die zu vergleichenden Zeichenketten identisch sind, andernfalls false.

  6. Erweitern Sie Ihr in Aufgabe 5 entwickeltes Java-Applet dahingehend, dass bei Eingabe von "Grün" und "Blau" die Hintergrundfarbe des Applets bei Enter auf die jeweilige Farbe gesetzt wird.

  7. Ändern Sie Ihr in Aufgabe 6 entwickeltes Java-Applet dahingehend, dass die Hintergrundfarbe des Applets nach Eingabe von "Rot", "Grün" oder "Blau" sofort gesetzt wird, ohne dass der Anwender Enter drücken muss.

  8. Entwickeln Sie eine Java-Application, die für eine gegebene Ganzzahl errechnet, ob es sich um eine Primzahl handelt oder nicht. Primzahlen erkennen Sie daran, dass sie nur durch sich selber und 1 dividiert werden können, ohne im Ergebnis eine Kommazahl zu erhalten. Geben Sie das Ergebnis der Berechnung jeweils auf die Standardausgabe aus.

  9. Erweitern Sie Ihre in Aufgabe 8 entwickelte Java-Application dahingehend, dass alle Primzahlen in einer vorgegebenen Bandbreite gefunden werden. Es wird ein Start- und Endwert vorgegeben, und Ihre Anwendung soll alle Primzahlen zwischen dem Start- und Endwert finden. Start- und Endwert sollen ebenfalls mitüberprüft werden, ob es sich bei ihnen um Primzahlen handelt.

  10. Ändern Sie Ihre in Aufgabe 9 entwickelte Java-Application dahingehend, dass gefundene Primzahlen nicht sofort auf die Standardausgabe ausgegeben werden, sondern in einem Array gespeichert werden. Wenn alle Primzahlen gefunden und im Array gespeichert wurden, geben Sie anschließend den Inhalt des Arrays auf die Standardausgabe aus. Geben Sie eine beliebige Größe für das Array vor und achten Sie darauf, dass möglicherweise mehr Primzahlen gefunden werden als im Array gespeichert werden können. Die Primzahlen, die nicht mehr im Array gespeichert werden können, können Sie ignorieren.