9. Ausnahmebehandlung Java-Beispiele: Ausnahme.java TryCatch.java TryCatchAll.java Finally.java TryInTry.java KeyboardTry.java Oeffnungszeit.java K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 Version: 18. Jan. 2007 Schwerpunkte • Ausnahmen und Laufzeitfehler • Stack-Trace • Java-Ausnahmeklassen-Hierarchie • try-catch: Nutzerdefinierte Ausnahmebehandlung • Nutzerdefinierte Erzeugung von Ausnahmen K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 2 Ausnahmen • Besondere Bedingungen zur Laufzeit des Programms: Fehlersituation • Keine sinnvolle Weiterarbeit: meist Laufzeitfehler Æ Abbruch des Programms Beispiele: • Array: falscher Index a[i] • Eingabe: Zahl erwartet - aber Buchstabe liegt an • Zugriff auf Objekt (Aufruf von Methoden): - existiert aber nur ’null’-Objekt • Klasse zur Laufzeit nicht vorhanden (nach Compilation: Klasse gelöscht) K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 Ziel: Trotz Ausnahme soll sinnvolle Weiterarbeit möglich sein 3 Laufzeitfehler und Ausnahmeinformationen Stack-Trace K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 4 Beispiele: Laufzeitfehler erzeugen Ausnahmen class Ausnahme { public static void main (String[] args) { int i = Integer.parseInt(args[0]); System.out.println("i = " + i); } } % java Ausnahme 3 i = 3 Ausgabe? % java Ausnahme java.lang.ArrayIndexOutOfBoundsException: 0 at Ausnahme.main(Compiled Code) % java Ausnahme a1 java.lang.NumberFormatException: a1 at java.lang.Integer.parseInt at Ausnahme.main K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 Vergleiche: Verschiedene ‘at’-Angaben 5 Inhalt von Ausnahme-Mitteilungen class Ausnahme { public static void main (String[] args){ int i = Integer.parseInt(args[0]); System.out.println("i = " + i); } } Was? Details Art % java Ausnahme a1 java.lang.NumberFormatException: at java.lang.Integer.parseInt at Ausnahme.main Wo: In welcher Umgebung? Æ Stack-Trace K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 a1 Wo: In welcher Methode (welcher Klasse)? 6 Au Stack-Trace sn ah me Umgekehrte Liste aller aktivierten, aber noch .ja va nicht beendeten Methoden-Aufrufe class Ausnahme { static int makeIntFromString (String s) return Integer.parseInt(s); } public static void main (String[] args) int i = makeIntFromString(args[0]); System.out.println("i = " + i); } } % java Ausnahme a1 java.lang.NumberFormatException: a1 at java.lang.Integer.parseInt Aufruf 3 at Ausnahme.makeIntFromString Aufruf 2 at Ausnahme.main Aufruf 1 K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 { { Ausgaberichtung (Stack) 7 Stack–Trace: Ausschriften nicht einheitlich % java Ausnahme a1 java.lang.NumberFormatException: at java.lang.Throwable at java.lang.Exception at java.lang.RuntimeException Konstruktoren zur Erzeugung von a1 Ausnahmeobjekten Æ Klassen-Hierarchie (Laufzeit-API-Stack-Trace wird durch JavaInterpreter gerufen) at java.lang.IllegalArgumentException at java.lang.NumberFormatException at java.lang.Integer.parseInt at Ausnahme.makeIntFromString at Ausnahme.main Java 1.3 K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 Stack-Trace (Anwenderprogramm) 8 Ausnahmebehandlung in Java K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 9 Ausnahmebehandlung in Java: objektorientierte Lösung class Ausnahme { static int makeIntFromString (String s) { return Integer.parseInt(s); } public static void main (String[] args) { int i = makeIntFromString(args[0]); System.out.println("i = " + i); } } Au sn ah me .ja va Aufrufreihenfolge (mit aktuellen Parametern) : % java Ausnahme a1 4 61 main({"a1", "4", "61"}) makeIntFromString("a1") Integer.parseInt("a1") K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 Java-VM-Maschine: - entdeckt Ausnahmesituation - erzeugt Objekt (einer Ausnahmeklasse) 10 Wie kann man sich Objekte zur Beschreibung von Ausnahmen vorstellen? Java-VM-Maschine: erzeugt Objekt (einer Ausnahmeklasse) ? K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 11 Wie kann man sich Objekte zur Beschreibung von Ausnahmen vorstellen? Java-VM-Maschine: erzeugt Objekt (einer Ausnahmeklasse) Objekt der Klasse NumberFormatException: NumberFormatException(String details) getMessage() printStrackTrace() FillInStackTrace() Art: NumberFormatException Details: a1 Stack-Trace: Integer.parseInt makeIntFromString main K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 12 Ausnahme-Klassen: Hierarchie (in java.lang) Throwable Error VirtualMachineError Exception ... RuntimeException IllegalArgumentException ... ... ... ArithmeticException NumberFormatException Beispielobjekt: je Art einer Ausnahme: spezielle Klasse NumberFormatException (String details) printStrackTrace() getMessage() FillInStackTrace() Art: NumberFormatException Details: a1 Stack-Trace: Integer.parseInt makeIntFromString main K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 Throwable: allgemeine Ausnahmeklasse Error: schwerer Fehler (i.allg. nicht behebbar) Exception: behandelbar 13 Ausnahmebehandlung bedeutet: Auswertung von erzeugten Ausnahmeobjekten Objekt der Klasse NumberFormatException NumberFormatException (String details) printStrackTrace() getMessage() FillInStackTrace() Art: NumberFormatException Details: a1 Stack-Trace: Integer.parseInt makeIntFromString main Wer wertet die Information aus? • Java-Standard-Ausnahmebehandler (JVM): - Ausgabe der im Ausnahmeobjekt gespeicherten Informationen (s.o.) - Abbruch des Programms • Nutzerdefinierte Ausnahmebehandlung: try-catch - Anweisung K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 14 Nutzerdefinierte Ausnahmebehandlung in Java: try-catch-Anweisung K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 15 try–catch: ein Beispiel T r yC atch .jav a class TryCatch { public static void main (String[] args) { try { Kritische int i = Integer.parseInt(args[0]); Anweisungen System.out.println("i = " + i); ÆAusnahme} catch (NumberFormatException e) { Situation System.out.println("Als Kommandozeilenmöglich Argument wird ein int-Wert benoetigt"); } } Behandlung } Æ danach: normale Weiterarbeit K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 16 try–catch: Wirkung im Detail class TryCatch { public static void main (String[] args) { try { int i = Integer.parseInt(args[0]); System.out.println("i = " + i); } try-Block: u.U. Ausnahme Æ Evtl. Ausnahmeobjekt o vom Typ (Klasse) t erzeugt: Falls t zum Typ des Parameters von catch passt: - Objekt o an e gebunden - catch–Anweisung ausgeführt catch (NumberFormatException e) { System.out.println("Als KommandozeilenArgument ..."); } Rolle von e? } Æ Programmierer bestimmt, was nach einer Ausnahme (hier: NumberFormatException) passiert und das Programm wird regulär fortgesetzt ! K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 17 try–catch: Aufruf class TryCatch { public static void main (String[] args) { try { int i = Integer.parseInt(args[0]); System.out.println("i = " + i); } catch (NumberFormatException e) { System.out.println("Als KommandozeilenArgument wird ein int-Wert benötigt"); } } } Ausgabe? % java TryCatch a1 falsches Argument Als Kommandozeilen-Argument wird ein int-Wert benötigt % java TryCatch fehlendes Argument java.lang.ArrayIndexOutOfBoundsException: 0 ... K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 18 Behandlung mehrerer Ausnahmen Try C atc class TryCatchAll { hA public static void main (String[] args) { ll.j av try { a int i = Integer.parseInt(args[0]); System.out.println("i = " + i); } catch (NumberFormatException e) { System.out.println("Als Kommandozeilen ..."); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Aufruf mit einem Par."); } catch (Throwable e) { Alle Ausnahmen sind e.printStackTrace(); kompatibel zu Throwable } } Methode auf Ausnahmeobjekt } Unterschied: angewendet letztes catch ÅÆ Interpreter? K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 19 Kompatibilität von Ausnahmen Throwable Error VirtualMachineError Exception ... RuntimeException IllegalArgumentException ... ... ... ArithmeticException NumberFormatException Regel: Ausnahme-Unterklassen sind immer kompatibel zur erwarteten Klasse, d.h. zu Throwable sind alle Ausnahmen kompatibel K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 Throwable: je Art einer Ausnahme: spezielle Klasse allgemeine Ausnahmeklasse Error: schwerer Fehler (i.allg. nicht behebbar) Exception: behandelbar 20 try-catch: reguläre Weiterarbeit class TryCatchAll { public static void main (String[] args) { try { ... } catch (NumberFormatException e) {... } catch (ArrayIndexOutOfBoundsException e) {... } catch (Throwable e) { ... } System.out.println ("Programm ordentlich beendet"); } Mit und ohne Ausnahme: } Ausschrift kommt Ohne try-catch: Programm nach Auftreten einer Ausnahme (irregulär) beendet K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 21 finally-Block - Am Ende: finally-Code immer ausgeführt (mit / ohne Ausnahme) Idee: gemeinsamer Code für Abschlussaktivitäten Fin al l y.j av a class Finally { public static void main (String[] args) { int i = 1000, j = 0; try { i /= j; } catch (ArithmeticException e) { System.out.println(e); } finally { System.out.println (i + " / 0 undef."); } } Hinweis kommt immer } % java Finally . . . 1000 / 0 undef. K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 22 Verschachtelte try-Anweisungen Try I try { try { int x = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.out.println("Innen: " + e); } Argument kein 'int' } catch (Throwable e) { System.out.println ("Aussen: " + e); } kein Argument nT ry. jav a Falls Ausnahme im inneren catch nicht passt: Suche umgebendes try-catch (bzw. try-catch einer aufrufenden Methode) K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 23 Beispiel: sicheres Einlesen von Zahlen public static int intEinlesen() { int zahl = 0; boolean ok = false; Ke yb oa rdT ry. j av System.out.print("Zahl eingeben: "); a while (!ok) { try { ok = true; zahl = Keyboard.readInt(); } catch ( NumberFormatException e ) { System.out.print("Keine Zahl!! Noch einmal:"); ok = false; } } return zahl; } K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 24 Nutzerdefinierte Erzeugung von Ausnahmen in Java: throw-Anweisung K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 25 Wer entdeckt Ausnahmesituationen? Wer erzeugt Ausnahmeobjekte? class Ausnahme { public static void main (String[] args) int i = Integer.parseInt(args[0]); System.out.println("i = " + i); } } Hier: Auswertung von Ausnahmeobjekten % java Ausnahme 3 i = 3 Frage: Wer hat sie vorher erzeugt? % java Ausnahme a1 java.lang.NumberFormatException: a1 at java.lang.Integer.parseInt at Ausnahme.main { % java Ausnahme java.lang.ArrayIndexOutOfBoundsException: 0 at Ausnahme.main(Compiled Code) K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 26 Wer erzeugt Ausnahmen? • Virtuelle Java-Maschine (Java-Interpreter): z.B. - Klasse nicht gefunden - falscher Array-Index • Methoden des Java-API z. B. Integer.parseInt (in Java implementiert) public static int parseInt (String s) throws NumberFormatException parseInt wertet s aus und erzeugt ggf. Ausnahme • Nutzer-Programm K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 27 Ausnahmen: erzeugen + behandeln Ausnahmesituation / Laufzeitfehler erzeugt Ausnahmeobjekt Java VM-Maschine (Index-Fehler) API-Methoden (parseInt) Nutzerprogramm wird ausgewertet Java-StandardAusnahmebehandlung Mitteilungen: ... Abbruch K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 nutzerdefinierte Behandlung: try-catch Weiterarbeit 28 Nutzerdefinierte Ausnahmen class Wochenende extends Exception { Wochenende(String text) { Oe ffnu super(text); } ngs zei t.ja } va ex = new Wochende ("Sonntag") ex.getMessage() Æ "Sonntag" Java-API class Exception { public Exception (String s) // erzeugt E. mit Information s public String getMessage () // gibt Information s zurueck ... } Programm arbeitet am Wochenende anders als in der Woche K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 29 Neue Ausnahmeklasse: 'Wochenende' Throwable Exception Error ... Wochenende RuntimeException IllegalArgumentException ... ... ... ArithmeticException NumberFormatException K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 30 Anwendung: nutzerdefinierte Ausnahme public static void main (String[] args) { try { Normalfall z. B. "Sonntag" heuteOffen(); } catch (Wochenende ex) { System.out.println ( ex.getMessage() + "s geschlossen."); Ausnahmesituation } } Methode erzeugt Ausnahme static void heuteOffen() throws Wochenende { int tag = Calender ... // API-Klasse if (tag == Calendar.SUNDAY) // 1 Im Ausnahmefall: throw new Wochenende("Sonntag"); nicht erreicht if (tag == Calendar.SATURDAY) // 7 throw new Wochenende("Samstag"); System.out.println("Heute geoeffnet."); } K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 31 Ausnahmeobjekt nach: throw new Wochende ("Sonntag"); Aufruf in: heuteOffen() Aufruf in: main() Wochenende (String details) printStrackTrace() getMessage () FillInStackTrace() Art: Wochenende Details: "Sonntag" Stack-Trace: Wochenende.heuteOffen Wochenende.main K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 32 API–Klasse Calender: liefert aktuellen Wochentag static void heuteOffen () throws Wochenende { int tag = Calendar.getInstance().get(Calendar.DAY_OF_WEEK); if (tag == Calendar.SUNDAY) // 1 throw new Wochenende("Sonntag"); aktueller Wochentag geliefert if (tag == Calendar.SATURDAY) // 7 throw new Wochenende("Samstag"); System.out.println("Heute geoeffnet."); } K. Bothe, Inst. f. Informatik, HU Berlin, PI1, WS 2006/07 33