Info B VL 6: Exceptions Objektorientiere Programmierung in Java 2003 Ute Schmid (Vorlesung) Elmar Ludwig (Übung) FB Mathematik/Informatik, Universität Osnabrück Info B VL 6: Exceptions – p.146 Fehler und Ausnahmen Exception Ereignis). exceptional event (aussergewöhnliches Ereignis, das während der Ausführung eines Programms auftritt und den normalen Ablauf unterbricht. Java: “Fehlerereignisse” als Objekte (vom Typ Exception) repräsentiert. Exception und Error erweitern Throwable. Error-Unterklassen betreffen schwerwiegende Fehler (z.B. VirtualMachineError) und sollten nicht vom Programmierer behandelt werden. Exceptions sollten dagegen behandelt werden. Exceptions treten typischerweise innerhalb von Methoden auf. Info B VL 6: Exceptions – p.147 Exception-Objekte Wenn eine Exception auftritt (z. B. FileNotFoundException wenn eine Datei, die geöffnet werden soll, nicht gefunden wird), wird ein Exception Objekt erzeugt und an das Laufzeitsystem throwing an exception gegeben. Dieses Objekt enthält Information über die Art der Exception und über den Zustand des Programms (Aufrufstack) zum Zeitpunkt zu dem die Exception auftrat. Das Laufzeitsystem ist verantwortlich, Code zu finden, der den Fehler behandelt. Die Behandlung kann in der Methode, in der der Fehler aufgetreten ist, selbst oder in einer der diese Methode aufrufenden Methoden (Aufrufstack) erfolgen. Info B VL 6: Exceptions – p.148 Exception-Handler Beispiel: h() -----------------> Exception tritt auf g() (ruft h() auf) f() (ruft g() auf) Behandlung der Exception Exception Handler (catch-Block): Für eine aufgetretene Exception ist derjenige Handler angemessen, der den entsprechenden Exception-Typ (Klasse oder Oberklasse des geworfenen Exceptionen-Objects) behandelt. Wird eine aufgetretene Exception nicht behandelt, terminiert das Laufzeitsystem und damit das Programm. Info B VL 6: Exceptions – p.149 Vorteile von Exceptions Separierung von regulärem Code und Fehlerbehandlung: Transparenz, Strukturiertheit Propagierung von Fehlern möglich Gruppierung von Fehler-Typen, Fehlerdifferenzierung Info B VL 6: Exceptions – p.150 Beispiel (in Pseudocode) readFile { open the file; determine its size; allocate that much memory; read the file into memory; close the file; } // // // // // // was ist, wenn file nicht geoeffnet werden kann? Laenge nicht bestimmt werden kann? nicht genug Speicher belegt werden kann? beim Lesen ein Fehler auftritt? file nicht geschlossen werden kann? Info B VL 6: Exceptions – p.151 Explizite Bedingungen errorCodeType readFile { initialize errorCode = 0; open the file; if (theFileIsOpen) { determine the length of the file; if (gotTheFileLength) { allocate that much memory; if (gotEnoughMemory) { read the file into memory; if (readFailed) { errorCode = -1; } } else { errorCode = -2; } } else { errorCode = -3; } close the file; if (theFileDidntClose && errorCode == 0) { errorCode = -4; } else { errorCode = errorCode and -4; } } else { errorCode = -5; } return errorCode; } Info B VL 6: Exceptions – p.152 Trennung von Code und Fehlerbeh. readFile { { // Block mit Anweisungen, wo Exc. auftreten koennten open the file; determine its size; allocate that much memory; read the file into memory; close the file; } handle fileOpenFailed { doSomething; } handle sizeDeterminationFailed { doSomething; } handle memoryAllocationFailed { doSomething; } handle readFailed { doSomething; } handle fileCloseFailed { doSomething; } } Info B VL 6: Exceptions – p.153 Propagieren von Exceptions (Beispiel in Pseudocode) method1 { call method2; } method2 { call method3; } method3 { call readFile; } Nur method1 sei an Fehlern, die in readFile() auftreten können interessiert. Info B VL 6: Exceptions – p.154 Propagierung “zu Fuss” method1 { errorCodeType error; error = call method2; if (error) doErrorProcessing; else proceed; } errorCodeType method2 { errorCodeType error; error = call method3; if (error) return error; else proceed; } errorCodeType method3 { errorCodeType error; error = call readFile; if (error) return error; else proceed; Info B VL 6: Exceptions – p.155 Propagierung mit ‘throws’ method1 { try { call method2; } catch (exception) { doErrorProcessing; } } method2 throws exception { call method3; } method3 throws exception { call readFile; } Info B VL 6: Exceptions – p.156 Exception-Spezifikation throws spezifiziert eine Exception: Exception ‘Name’ kann in Methode ‘method’ auftreten Spezifikation statt Behandlung: duck a thrown exception Behandlung mit catch Laufzeitfehler müssen nicht spezifiziert/behandelt werden Alle anderen Exceptions dagegen schon! (checked exceptions) Beispielcode: CloneCircle.java javac CloneCircle.java CloneCircle.java:89: unreported exception java.lang.CloneNotSupportedException; must be caught or declared to be thrown return super.clone(); ˆ Info B VL 6: Exceptions – p.157 ‘RunTimeException’ o class java.lang.RuntimeException + class java.lang.ArithmeticException + class java.lang.ArrayStoreException + class java.lang.ClassCastException + class java.lang.IllegalArgumentException class java.lang.IllegalThreadStateException class java.lang.NumberFormatException + class java.lang.IllegalMonitorStateException + class java.lang.IllegalStateException + class java.lang.IndexOutOfBoundsException class java.lang.ArrayIndexOutOfBoundsException class java.lang.StringIndexOutOfBoundsException + class java.lang.NegativeArraySizeException + class java.lang.NullPointerException + class java.lang.SecurityException + class java.lang.UnsupportedOperationException Info B VL 6: Exceptions – p.158 Checked Exceptions Beispiele: CloneNotSupportedException, IOException und Unterklassen werden von Methoden ausgelöst, RunTimeExceptions vom Laufzeitsystem. Es macht Sinn, dass verlangt wird, dass alle Fehler ausser RunTimeExceptions vom Programmierer behandelt werden. Der Compiler/das Laufzeitsystem können nicht hellsehen, auf welche Art eine Exception behandelt werden soll. Beispiel FileNotFoundException: Programm beenden, andere Datei einlesen, File dieses Namens erzeugen. Info B VL 6: Exceptions – p.159 Gruppierung von Fehlertypen Exception-Objekte sind – wie andere Java Objekte – in einer Klassenhierarchie organisiert. Alle Exceptions sind Instanzen von Throwable. Ganze Gruppen von Exceptions können gemeinsam behandelt werden, wenn eine entsprechende Oberklasse verwendet wird. Wenn mehrere catch-Blöcke den Typ der Exception behandeln, so wird nur der erste (Reihenfolge im Code) passende ausgeführt. sequentielle Behandlung von der speziellsten zur allgemeinsten Achtung: Exception-Handler, die zu allgemein sind, können Code wieder fehleranfällig machen! Es können dadurch Exceptions gefangen werden, die nicht vorhergesehen wurden und entsprechend nicht korrekt Info B VL 6: Exceptions – p.160 behandelt werden. Spezififkation mit ‘throws’ Beispielprogramm: ListOfNumbersDeclared.java throws spezifiziert mögliche Fehler und verschiebt deren Behandlung zu aufrufenden Methoden. Dies macht Sinn, wenn es übergeordnete Strukturen gibt, bei denen erst klar ist, welche Fehler wie abgefangen werden sollen. Es macht wenig Sinn, dass die main-Methode (letzte Methode im Aufrufstack) Fehler spezifiziert und nicht behandelt. Programmbenutzer wird dann mit den java-Fehlermeldungen konfrontiert. throws kann nur für Methoden (und Konstruktoren) deklariert werden. Info B VL 6: Exceptions – p.161 Vererbung und ‘throws’ Es ist nicht erlaubt, einer Methode beim Überschreiben weitere throws-Klauseln hinzuzufügen! Ansonsten wäre keine Zuweisungskompatibilität mehr gegeben: In allen Methoden, die diese Methode verwenden, müsste eine Spezifikation bzw. Behandlung der neu hinzugekommenen Exceptions erfolgen, was durch Casting zur Oberklasse umgangen werden könnte. Weglassen eines Teils oder einer kompletten throws-Klausel ist erlaubt. Info B VL 6: Exceptions – p.162 Exception Handling (1) try -- catch -- finally try-catch-finally ist eine Kontrollstruktur. try-Block: wird verlassen, sobald eine Exception auftritt catch-Block: Fehlerbehandlung (es kann mehrere catch-Blöcke geben) finally-Block: sichert, dass bestimmte Dinge auf jeden Fall ausgeführt werden (wenn vorher kein System.exit() erfolgt), auch wenn etwas schief geht. Beispiel: Schliessen einer Datei Info B VL 6: Exceptions – p.163 Exception Handling (2) try-finally: keine Fehlerbehandlung, sondern Vermeidung von Redundanz im Code: Anweisungen in finally werden auf jeden Fall ausgeführt (egal ob der try-Block regulär oder wegen Exception verlassen wird) try-catch: Fehlerbehandlung Exception-Objekte haben die Methode getMessage(), die den Fehlertext der Exception liefert. Fehlermeldung in catch: mit System.err.println() sinnvoller als System.out.println(): Fehler-Strom soll auf Terminal, während der Ausgabestrom z.B. in eine Datei gehen kann. Info B VL 6: Exceptions – p.164 Beispiel Beispielcode: ListOfNumbers.java Drei Möglichkeiten des Programmablaufs: new FileWriter() geht schief, IOException: Entering try statement Caught IOException: OutFile.txt PrintWriter not open ArrayIndexOutOfBoundsException: Entering try statement Caught ArrayIndexOutOfBoundsException: 10 >= 10 Closing PrintWriter try-Block wird ohne Exception verlassen Entering try statement Closing PrintWriter Info B VL 6: Exceptions – p.165 Definition und Auslösen von Excs. Neue Exception-Klasse als Unterklasse von Exception throw new Exception() in Methode Beispiel: IllegalRadiusException.java, CheckedCircle Info B VL 6: Exceptions – p.166 Exkurs: UML UML (“Unified Modeling Language”) ist eine auf Diagrammen basierende Beschreibungssprache für den objekt-orientierten Entwurf und die objekt-ortientierte Analyse. Standardisierte Notation zur Repräsentation von Klassen und ihren Beziehungen Standardisierung durch: Booch, Jacobson, Rumbaugh (“Die drei Amigos”). Meta-Modell legt fest, wie diese Sprache benutzt werden soll. Objekt-orientierter Entwurf meint die Konzeption von Klassenstrukturen und Abhängigkeiten bei der Systementwicklung. Vorteile einer standardisierten Sprache: CASE-Tools, Austausch von Entwürfen Info B VL 6: Exceptions – p.167 Klassendiagramme public abstract class Person { protected String personName; private int age; public Person (String name) { personName = name; } static public String makeJob () {return "hired";} public int getAge () {return age;} private void splitNames () {} abstract String getJob (); } Info B VL 6: Exceptions – p.168 Beispiele +Person +getAge getJob +makeJob −splitNames Sichtbarkeits-Modifikatoren: public, private, protected −age #personName Person Kasten aus drei Teilen: Klassen-Namen (fett), Felder, Methoden Kursiv: Abstrakte Klassen/Methoden Unterstrichen: Klassen-Methoden, Felder Info B VL 6: Exceptions – p.169 Beispiele Person −age: Integer #personName: String Person +Person(String) +getAge(): Integer getJob(): String +makeJob(): String −splitNames() +getAge getJob +makeJob −splitNames Info B VL 6: Exceptions – p.170 Generalisierung public class Employee extends Person { public Employee (String name) { super(name); } public String getJob() { return "Research Staff"; } } Employee +Employee +getJob Person +getAge getJob +makeJob −splitNames Info B VL 6: Exceptions – p.171 Assoziationen Allgemeine Beziehung zwischen Klassen (bzw. Objekten): Linie Spezielle Assoziationen: Generalisierung: ungefüllter Pfeil Aggregation (Teil-Ganzes): ungefüllte Raute Komposition (Teile können nicht ohne Ganzes existieren): gefüllte Raute Allgemein: Rolle, die einge Klasse bzgl. einer anderen spielt Rekursive Assoziation Info B VL 6: Exceptions – p.172 Beispiel public class Company { Employee empt1; Person per1; public Company() {} } Person Employee public class Company1 { Employee[] emp1; public Company1() {} } 0..1 per1 Company 0..1 emp1 Employee * emp1 Company1 Info B VL 6: Exceptions – p.173