From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100080.html | 652 +++++++++++++++++++++ 1 file changed, 652 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100080.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100080.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100080.html b/Master/Reference Architectures and Patterns/hjp5/html/k100080.html new file mode 100644 index 0000000..85b751f --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100080.html @@ -0,0 +1,652 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 12 - Exceptions +
+
+ + + + +

12.2 Behandlung von Exceptions

+
+ +
+ + + + +

12.2.1 Die try-catch-Anweisung

+ +

+Das Behandeln von Ausnahmen erfolgt mit Hilfe der try-catch-Anweisung: + + +

+ + + + +
+ +
+001 try {
+002   Anweisung;
+003   ...
+004 } catch (Ausnahmetyp x) {
+005   Anweisung;
+006   ...
+007 }
+
+
+ +Listing 12.1: Die try-catch-Anweisung

+ +

+Der try-Block +enthält dabei eine oder mehrere Anweisungen, bei deren Ausführung +ein Fehler des Typs Ausnahmetyp +auftreten kann. In diesem Fall wird die normale Programmausführung +unterbrochen, und der Programmablauf fährt mit der ersten Anweisung +nach der catch-Klausel +fort, die den passenden Ausnahmetyp deklariert hat. Hier kann nun +Code untergebracht werden, der eine angemessene Reaktion auf den Fehler +realisiert. + +

+Wir wollen das folgende fehlerhafte Programm betrachten: + + +

+ + + + + +
+ +
+001 /* RTErrorProg1.java */
+002 
+003 public class RTErrorProg1
+004 {
+005   public static void main(String[] args)
+006   {
+007     int i, base = 0;
+008 
+009     for (base = 10; base >= 2; --base) {
+010       i = Integer.parseInt("40",base);
+011       System.out.println("40 base "+base+" = "+i);
+012     }
+013   }
+014 }
+
+
+RTErrorProg1.java
+ +Listing 12.2: Ein Programm mit einem Laufzeitfehler

+ +

+Hier soll der String »40« aus verschiedenen Zahlensystemen +in ein int +konvertiert und als Dezimalzahl ausgegeben werden. Die dazu verwendete +Methode parseInt +überprüft, ob der übergebene String einen gültigen +Zahlenwert zur angegebenen Basis darstellt. Ist dies nicht der Fall, +löst sie eine Ausnahme des Typs NumberFormatException +aus. Ohne weitere Maßnahmen stürzt das Programm dann beim +Versuch, den String »40« als Zahl zur Basis 4 anzusehen, +ab: + +

+40 base 10 = 40
+40 base 9 = 36
+40 base 8 = 32
+40 base 7 = 28
+40 base 6 = 24
+40 base 5 = 20
+Exception in thread "main" java.lang.NumberFormatException: 40
+        at java.lang.Integer.parseInt(Compiled Code)
+        at RTErrorProg1.main(Compiled Code)
+
+ + +

+Das Programm läßt sich nun leicht gegen solche Fehler absichern, +indem die Programmsequenz, die den Fehler verursacht, in eine try-catch-Anweisung +eingeschlossen wird: + + +

+ + + + + +
+ +
+001 /* Listing1203.java */
+002 
+003 public class Listing1203
+004 {
+005   public static void main(String[] args)
+006   {
+007     int i, base = 0;
+008 
+009     try {
+010       for (base = 10; base >= 2; --base) {
+011         i = Integer.parseInt("40",base);
+012         System.out.println("40 base "+base+" = "+i);
+013       }
+014     } catch (NumberFormatException e) {
+015       System.out.println(
+016         "40 ist keine Zahl zur Basis "+base
+017       );
+018     }
+019   }
+020 }
+
+
+Listing1203.java
+ +Listing 12.3: Abfangen des Laufzeitfehlers mit einer try-catch-Anweisung

+ +

+Zwar ist 40 immer noch keine Zahl zur Basis 4, aber das Programm fängt +diesen Fehler nun ab und gibt eine geeignete Fehlermeldung aus: + +

+40 base 10 = 40
+40 base 9 = 36
+40 base 8 = 32
+40 base 7 = 28
+40 base 6 = 24
+40 base 5 = 20
+40 ist keine Zahl zur Basis 4
+
+ + + + + +

12.2.2 Das Fehlerobjekt

+ +

+In der catch-Klausel +wird nicht nur die Art des abzufangenden Fehlers definiert, sondern +auch ein formaler Parameter angegeben, der beim Auftreten der Ausnahme +ein Fehlerobjekt übernehmen soll. Fehlerobjekte sind dabei Instanzen +der Klasse Throwable +oder einer ihrer Unterklassen. Sie werden vom Aufrufer der Ausnahme +erzeugt und als Parameter an die catch-Klausel +übergeben. Das Fehlerobjekt enthält Informationen über +die Art des aufgetretenen Fehlers. So liefert beispielsweise die Methode +getMessage +einen Fehlertext (wenn dieser explizit gesetzt wurde), und printStackTrace +druckt einen Auszug aus dem Laufzeit-Stack. Am einfachsten kann der +Fehlertext mit der Methode toString +der Klasse Throwable +ausgegeben werden: +

+ + + + + +
+ +
+public String getMessage()
+
+public void printStackTrace()
+
+public String toString()
+
+
+
+java.lang.Throwable
+ +

+Unser Beispielprogramm könnte dann wie folgt umgeschrieben werden: + + +

+ + + + + +
+ +
+001 /* RTErrorProg2.java */
+002 
+003 public class RTErrorProg2
+004 {
+005   public static void main(String[] args)
+006   {
+007     int i, base = 0;
+008 
+009     try {
+010       for (base = 10; base >= 2; --base) {
+011         i = Integer.parseInt("40",base);
+012         System.out.println("40 base "+base+" = "+i);
+013       }
+014     } catch (NumberFormatException e) {
+015       System.out.println("***Fehler aufgetreten***");
+016       System.out.println("Ursache: "+e.getMessage());
+017       e.printStackTrace();
+018     }
+019   }
+020 }
+
+
+RTErrorProg2.java
+ +Listing 12.4: Verwendung des Fehlerobjekts nach einem Laufzeitfehler

+ +

+Die Ausgabe des Programms wäre dann: + +

+40 base 10 = 40
+40 base 9 = 36
+40 base 8 = 32
+40 base 7 = 28
+40 base 6 = 24
+40 base 5 = 20
+***Fehler aufgetreten***
+Ursache: 40
+java.lang.NumberFormatException: 40
+        at java.lang.Integer.parseInt(Compiled Code)
+        at RTErrorProg2.main(Compiled Code)
+
+ + +

+Wie man sieht, ähnelt die Ausgabe des Programms der ersten Version, +die ohne expliziten Fehler-Handler geschrieben wurde. Das liegt daran, +dass das Java-Laufzeitsystem beim Auftreten eines Fehlers, der von +keiner Methode behandelt wurde, printStackTrace +aufruft, bevor es das Programm beendet. + + + + +

12.2.3 Die Fehlerklassen von Java

+ +

+Alle Laufzeitfehler in Java sind Unterklassen der Klasse Throwable. +Throwable +ist eine allgemeine Fehlerklasse, die im wesentlichen eine Klartext-Fehlermeldung +speichern und einen Auszug des Laufzeit-Stacks ausgeben kann. Unterhalb +von Throwable +befinden sich zwei große Vererbungshierarchien: +

+ +

+Viele Pakete der Java-Klassenbibliothek definieren ihre eigenen Fehlerklassen. +So gibt es spezielle Fehlerklassen für die Dateiein- und -ausgabe, +die Netzwerkkommunikation oder den Zugriff auf Arrays. Wir werden +diese speziellen Fehlerklassen immer dann erläutern, wenn eine +Methode besprochen wird, die diese Art von Fehler erzeugt. + + + + +

12.2.4 Fortfahren nach Fehlern

+ +

+Die Reaktion auf eine Ausnahme muss keinesfalls zwangsläufig +darin bestehen, das Programm zu beenden. Statt dessen kann auch versucht +werden, den Fehler zu beheben oder zu umgehen, um dann mit dem Programm +fortzufahren. Wird im obigen Programm die try-catch-Anweisung +in die Schleife gesetzt, so fährt das Programm nach jedem Fehler +fort und versucht, die Konvertierung zur nächsten Basis vorzunehmen: + + +

+ + + + + +
+ +
+001 /* Listing1205.java */
+002 
+003 public class Listing1205
+004 {
+005   public static void main(String[] args)
+006   {
+007     int i, base = 0;
+008 
+009     for (base = 10; base >= 2; --base) {
+010       try {
+011         i = Integer.parseInt("40",base);
+012         System.out.println("40 base "+base+" = "+i);
+013       } catch (NumberFormatException e) {
+014         System.out.println(
+015           "40 ist keine Zahl zur Basis "+base
+016         );
+017       }
+018     }
+019   }
+020 }
+
+
+Listing1205.java
+ +Listing 12.5: Fortfahren nach Laufzeitfehlern

+ +

+Die Ausgabe des Programms lautet nun: + +

+40 base 10 = 40
+40 base 9 = 36
+40 base 8 = 32
+40 base 7 = 28
+40 base 6 = 24
+40 base 5 = 20
+40 ist keine Zahl zur Basis 4
+40 ist keine Zahl zur Basis 3
+40 ist keine Zahl zur Basis 2
+
+ +

+ + + + + + + + + +
+ +

+Ob es sinnvoller ist, nach einem Fehler mit der Programmausführung +fortzufahren oder das Programm abzubrechen, ist von der Art des Fehlers +und der Stelle im Programm, an der er aufgetreten ist, abhängig. +Hier muss von Fall zu Fall entschieden werden, wie vorgegangen werden +soll.

+ + + + +
 Hinweis 
+
+ + + + +

12.2.5 Mehr als eine catch-Klausel

+ +

+Bisher sind wir davon ausgegangen, dass innerhalb eines try-Blocks +nur eine Ausnahme auftreten kann. Tatsächlich ist es natürlich +ohne weiteres möglich, dass zwei oder mehrere unterschiedliche +Ausnahmen ausgelöst werden. Das Programm kann auf verschiedene +Fehler reagieren, indem es mehr als eine catch-Klausel +verwendet. Jede catch-Klausel +fängt die Fehler ab, die zum Typ des angegebenen Fehlerobjekts +zuweisungskompatibel sind. Dazu gehören alle Fehler der angegebenen +Klasse und all ihrer Unterklassen (das wichtige Konzept der Zuweisungskompatibilität +von Objekttypen wurde in Abschnitt 7.1.6 +erläutert). Die einzelnen catch-Klauseln +werden in der Reihenfolge ihres Auftretens abgearbeitet. + +

+Wir wollen das Beispielprogramm nun so erweitern, dass nicht nur ein +einzelner String in eine Zahl konvertiert wird, sondern ein Array +von Strings. Aufgrund eines Fehlers in der verwendeten for-Schleife +verursacht das Programm einen Zugriff auf ein nicht vorhandenes Array-Element +und löst damit eine Ausnahme des Typs IndexOutOfBoundsException +aus. Diese kann zusammen mit der Ausnahme NumberFormatException +in einer gemeinsamen try-catch-Anweisung +behandelt werden: + + +

+ + + + + +
+ +
+001 /* Listing1206.java */
+002 
+003 public class Listing1206
+004 {
+005   public static void main(String[] args)
+006   {
+007     int i, j, base = 0;
+008     String[] numbers = new String[3];
+009 
+010     numbers[0] = "10";
+011     numbers[1] = "20";
+012     numbers[2] = "30";
+013     try {
+014       for (base = 10; base >= 2; --base) {
+015         for (j = 0; j <= 3; ++j) {
+016           i = Integer.parseInt(numbers[j],base);
+017           System.out.println(
+018             numbers[j]+" base "+base+" = "+i
+019           );
+020         }
+021       }
+022     } catch (IndexOutOfBoundsException e1) {
+023       System.out.println(
+024         "***IndexOutOfBoundsException: " + e1.toString()
+025       );
+026     } catch (NumberFormatException e2) {
+027       System.out.println(
+028         "***NumberFormatException: " + e2.toString()
+029       );
+030     }
+031   }
+032 }
+
+
+Listing1206.java
+ +Listing 12.6: Mehr als eine catch-Klausel

+ +

+Die Ausgabe des Programms ist nun: + +

+10 base 10 = 10
+20 base 10 = 20
+30 base 10 = 30
+***IndexOutOfBoundsException: java.lang.ArrayIndexOutOfBoundsException
+
+ + + + + +

12.2.6 Die finally-Klausel

+ +

+Die try-catch-Anweisung +enthält einen optionalen Bestandteil, der bisher noch nicht erläutert +wurde. Mit Hilfe der finally-Klausel, +die als letzter Bestandteil einer try-catch-Anweisung +verwendet werden darf, kann ein Programmfragment definiert werden, +das immer dann ausgeführt wird, wenn die zugehörige try-Klausel +betreten wurde. Dabei spielt es keine Rolle, welches Ereignis +dafür verantwortlich war, dass die try-Klausel +verlassen wurde. Die finally-Klausel +wird insbesondere dann ausgeführt, wenn der try-Block +durch eine der folgenden Anweisungen verlassen wurde: +

+

+ + + + + + + + + +
+ +

+Die finally-Klausel +ist also der ideale Ort, um Aufräumarbeiten durchzuführen. +Hier können beispielsweise Dateien geschlossen oder Ressourcen +freigegeben werden.

+ + + + +
 Hinweis 
+
+ +

+Die folgende Variation unseres Beispielprogramms benutzt finally +dazu, am Ende des Programms eine Meldung auszugeben: + + +

+ + + + + +
+ +
+001 /* Listing1207.java */
+002 
+003 public class Listing1207
+004 {
+005   public static void main(String[] args)
+006   {
+007     int i, base = 0;
+008 
+009     try {
+010       for (base = 10; base >= 2; --base) {
+011         i = Integer.parseInt("40",base);
+012         System.out.println("40 base "+base+" = "+i);
+013       }
+014     } catch (NumberFormatException e) {
+015       System.out.println(
+016         "40 ist keine Zahl zur Basis "+base
+017       );
+018     } finally {
+019       System.out.println(
+020         "Sie haben ein einfaches Beispiel " +
+021         "sehr glücklich gemacht."
+022       );
+023     }
+024   }
+025 }
+
+
+Listing1207.java
+ +Listing 12.7: Verwendung der finally-Klausel

+ +

+Die Ausgabe des Programms ist: + +

+40 base 10 = 40
+40 base 9 = 36
+40 base 8 = 32
+40 base 7 = 28
+40 base 6 = 24
+40 base 5 = 20
+40 ist keine Zahl zur Basis 4
+Sie haben ein einfaches Beispiel sehr glücklich gemacht.
+
+ +
+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3