Programmieren in Java: Einführung


Kapitel 9: Exception Handling


Inhaltsverzeichnis

Dieses Buch ist unter einer Creative Commons-Lizenz lizensiert.


9.1 Allgemeines

Methoden können fehlschlagen

Exception Handling wird ins Deutsche als Behandlung von Ausnahmen übersetzt. Mit Ausnahmen sind Fehlersituationen gemeint, die in einem Programm während der Ausführung entstehen können und auf die geeignet reagiert werden muss.

Es gibt tatsächlich Methoden in Java, die fehlschlagen können. Es kann zu Fehlersituationen kommen, die nicht vorhersehbar sind. Tatsächlich gibt es sogar eine unüberschaubare Anzahl an Methoden in den Standard-Klassen, die fehlschlagen können und zu Ausnahmesituationen führen können. Wie auf derartige Ausnahmen reagiert wird, erfahren Sie in diesem Kapitel.


9.2 try-catch-Anweisung

Ausnahmen abfangen

Die entscheidene Anweisung im Zusammenhang mit Exception Handling ist die try-catch-Anweisung. Ihr grundsätzlicher Aufbau sieht wie folgt aus.

try 
{ 
  ANWEISUNGSBLOCK 
} 
catch (AUSNAHME) 
{ 
  ANWEISUNGSBLOCK 
} 

Die try-catch-Anweisung besteht aus zwei Anweisungsblöcken. Der erste Anweisungsblock folgt dem Schlüsselwort try, der zweite dem Schlüsselwort catch. Beachten Sie, dass hinter catch eine runde Klammer angegeben wird, über die eine Ausnahme abgefangen werden kann.

Welchen Sinn hat die try-catch-Anweisung und wie funktioniert sie? In den ersten Anweisungsblock hinter try fügen Sie Ihre eigentlichen Anweisungen ein, die ausgeführt werden sollen. Sie erstellen Objekte, greifen über Referenzvariablen auf diese zu, rufen Methoden auf und so weiter. Je nachdem, auf welche Klassen Sie zugreifen, welche Objekte Sie verwenden und welche Methoden Sie aufrufen besteht die Gefahr, dass Methoden fehlschlagen. Daraufhin treten Ausnahmesituationen ein.

Die Standardreaktion, wenn Ausnahmesituationen eintreten, sieht so aus, dass die Anwendung gewaltsam beendet wird. Man könnte auch sagen sie stürzt ab. Dies ist selbstverständlich ein Verhalten, das für professionelle Anwendungen nicht in Frage kommt. Es darf nicht sein, dass irgendwo im Code eine Anweisung fehlschlägt und das Programm vor den Augen des Anwenders crasht.

Sollten Sie also Methoden verwenden, die möglicherweise fehlschlagen und Ausnahmesituationen auslösen, dann können Sie hinter dem try-Anweisungsblock entsprechende Ausnahmen mit catch abfangen. Hierzu geben Sie in die runden Klammern hinter dem Schlüsselwort catch an, auf welche Ausnahmesituation Sie genau reagieren möchten. Tritt genau die Ausnahmesituation ein, auf die das catch lauert, wird der Anweisungsblock hinter dem catch ausgeführt. Diesen könnten Sie zum Beispiel nutzen, um dem Anwender eine entsprechende Fehlermeldung zu präsentieren. Sie könnten auch im catch-Anweisungsblock momentan vom Anwender im Java-Programm verwendete Daten speichern und dann das Programm beenden. Dies ist alles besser als die Anwendung einfach abstürzen zu lassen.

Woher wissen Sie, welche Methoden möglicherweise fehlschlagen und zu Ausnahmesituationen führen? Hier hilft nur der Blick in die Dokumentation. Dort ist zu jeder Methode angegeben, ob sie und wenn ja zu welchen Ausnahmesituationen sie führen kann.


9.3 Praxis-Beispiel

Zeichenketten in Zahlen umwandeln

Seit der allerersten Java-Version 1.0 gibt es eine Klasse java.lang.Integer, die verschiedene Methoden zur Verarbeitung von int-Werten zur Verfügung stellt. Unter anderem bietet diese Klasse auch eine Methode an, um eine Zahl in Form einer Zeichenkette in einen int-Wert umzurechnen. Es handelt sich hierbei um die statische Methode parseInt(), die als einzigen Parameter eine Zeichenkette, also einen String übergeben bekommt.

int zahl = Integer.parseInt("10"); 

Wird parseInt() so wie im obigen Beispiel die Zahl "10" in Form einer Zeichenkette übergeben, wird die Variable zahl vom Typ int auf den Wert 10 gesetzt.

Sehen Sie sich nun folgenden Code an.

int zahl = Integer.parseInt("abc"); 

Nun gibt es ein Problem: Der Methode parseInt() wird eine Zeichenkette übergeben, die gar keine Zahl enthält. Welcher Wert soll nun von parseInt() zurückgegeben und in der int-Variablen zahl gespeichert werden? Wenn Sie einen Blick in die Dokumentation der Klasse java.lang.Integer werfen und nach der Methode parseInt() suchen, stellen Sie fest, dass in dem Fall, in dem keine Zahl in der Zeichenkette als Parameter übergeben wird, eine Ausnahme vom Typ NumberFormatException eintritt.

Ausnahmesituationen werden in Java über Klassen identifiziert. Und wie üblich liegen Klassen in Java in verschiedenen Paketen. Die Klasse NumberFormatException liegt im Paket java.lang. Tritt also eine Ausnahmesituation ein, in der eine Umwandlung von Zahlen in Form von Zeichenketten in int-Werte fehlschlägt, lässt sich dies durch die Klasse java.lang.NumberFormatException erkennen.

Wie muss nun die try-catch-Anweisung verwendet werden, um die Ausnahmesituation unter Kontrolle zu bringen?

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    try 
    { 
      int zahl = Integer.parseInt("abc"); 
      System.out.print(zahl); 
    } 
    catch (NumberFormatException ex) 
    { 
      System.out.print("Der Wert abc konnte nicht umgewandelt werden."); 
    } 
  } 
} 

Ihr eigentlicher Code, den Sie ausführen möchten, wird in den try-Anweisungsblock gestellt. Nachdem Sie in Ihrem Code eine Methode verwenden, die eine Ausnahmesituation vom Typ NumberFormatException auslösen kann, fangen Sie genau diese Ausnahmesituation mit einem catch hinter dem try-Anweisungsblock ab. Dazu stellen Sie den Namen der Klasse, der die Ausnahmesituation kennzeichnet, zwischen die runden Klammern hinter catch und geben dahinter einen beliebigen Variablennamen an. Genaugenommen definieren Sie also in den runden Klammern hinter catch eine Variable.

Sie müssen sich den catch-Anweisungsblock als eine Art Methode vorstellen. Wenn im try-Anweisungsblock die Umwandlung der Zeichenkette in den int-Wert fehlschlägt, wird automatisch ein Objekt vom Typ NumberFormatException erstellt und geworfen. Man spricht tatsächlich davon, dass die Methode, die die Ausnahmesituation auslöst, ein Objekt wirft.

Dieses Objekt fliegt nun durch Ihre Methode. Ab der Code-Zeile, in der eine Ausnahmesituation eintritt und ein Objekt geworfen wird, werden keine darauffolgenden Anweisungen im try-Block mehr ausgeführt. Stattdessen sucht Java nach einem catch, das genau das Objekt abzufangen versucht, das im try-Block geworfen wurde. Wenn also im try-Anweisungsblock ein Objekt vom Typ NumberFormatException geworfen wird und Sie in einem anschließenden catch auf ein Objekt vom Typ NumberFormatException warten, wird nun der Anweisungsblock hinter dem catch ausgeführt. Dort implementieren Sie die Fehlerbehandlungsroutine.

Der Variablenname in den Klammern hinter catch stellt also eine Art Parameter dar, wie Sie es von Methodendefinitionen kennen. Über diesen Variablennamen ist ein Zugriff auf das Objekt möglich, das im try-Block geworfen wurde. So können Sie möglicherweise Methoden für dieses Objekt im catch-Anweisungsblock aufrufen, um weitere Informationen zur eingetretenen Ausnahmesituation zu erhalten.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    try 
    { 
      int zahl = Integer.parseInt("abc"); 
      System.out.print(zahl); 
    } 
    catch (NumberFormatException ex) 
    { 
      System.out.print(ex.getMessage()); 
    } 
  } 
} 

Alle Klassen, die in Java zur Identifizierung von Ausnahmesituationen verwendet werden, sind von der Klasse java.lang.Throwable abgeleitet - so auch NumberFormatException. Die Klasse Throwable definiert unter anderem eine Methode getMessage(), die durch Vererbung auch allen anderen Klassen im Zusammenhang mit Exception Handling zur Verfügung steht - also auch NumberFormatException. Diese Methode gibt eine Fehlerbeschreibung vom Typ String zurück, die im obigen Beispiel nun einfach auf die Standardausgabe ausgegeben wird.

Es hängt von der jeweils verwendeten Java-VM ab, welche Fehlermeldung genau zurückgegeben wird. Im Falle der Java-VM aus dem JDK 6 von Sun Microsystems wird auf die Standardausgabe lediglich die Zeichenkette "abc" ausgegeben. Somit ist bei Ausnahmen vom Typ NumberFormatException immerhin erkennbar, welcher Wert nicht umgewandelt werden konnte und die Ausnahmesituation ausgelöst hat.


9.4 Aufgaben

Übung macht den Meister

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

  1. Entwickeln Sie eine Java-Application, in der die Zeichenkette "16.09.2002" interpretiert und als gültiges Datum erkannt wird. Verwenden Sie hierzu die Methode parse() der Klasse java.text.DateFormat. Es handelt sich nicht um eine statische Methode, so dass Sie sich vorher ein Objekt vom Typ java.text.DateFormat beschaffen müssen. Dies tun Sie, indem Sie die statische Methode getDateInstance() für die Klasse java.text.DateFormat aufrufen, die ein Objekt vom Typ java.text.DateFormat zurückgibt. Die Zeichenkette "16.09.2002" wird als einziger Parameter an die Methode parse() übergeben. Kann die Zeichenkette nicht als gültiges Datum identifiziert werden, tritt eine Ausnahmesituation vom Typ java.text.ParseException ein. Wird die Zeichenkette als gültiges Datum interpretiert, gibt parse() ein Objekt vom Typ java.util.Date zurück. Rufen Sie für dieses Objekt die Methode toString() auf, die keinen Parameter erwartet und die Zeit in Form eines Strings zurückgibt. Geben Sie diesen String zur Kontrolle auf die Standardausgabe aus.

  2. Entwickeln Sie eine Java-Application, in der Sie ein beliebig großes Array eines beliebigen Datentypen erstellen. Greifen Sie auf das Array zu, indem Sie absichtlich einen ungültigen Index in eckigen Klammern verwenden. In diesem Fall tritt eine Ausnahmesituation vom Typ java.lang.ArrayIndexOutOfBoundsException ein. Erweitern Sie Ihren Code um eine try-catch-Klausel, um diese Ausnahme abzufangen.