class: center, middle, first # Software-Entwicklung 2 ### Exceptions --- # Fragen? > Fragen zur letzten Vorlesung? --- # Themen - Exceptions * Wieso Exceptions? * Exceptions Syntax * `throw`-Anweisung: Wir werfen oder leiten Exceptions weiter * `finally`-Anweisung: Vor der Weiterleitung schliessen wir offene Resourcen * `RuntimeException`: Exceptions die wir nicht extra deklarieren * `Checked Exceptions (throws)`: Wir zwingen Aufrufer zu try-catch Blöcken * `Eigene Exceptions`: Wir entwerfen eigene Business Exceptions --- # Wieso Exceptions?
--- # Wieso Exceptions? > Wir programmieren nur für den "Gut-Fall" statt endlos Return-Codes abzufragen * Eine Exception ist also eher ein unerwarteter Fehlerfall * Syntaxfehler im GUI sind eher keine Exceptions. Gleich dort behandeln. --- # Klassenhierarchie der Exceptions
_Quelle: [Java ist auch eine Insel - 6.3 Die Klassenhierachie der Fehler][javainsel02]_ --- # Klassenhierarchie - `Exception`
Nur von Error oder RuntimeException abgeleitete Exceptions brauchen nicht deklariert werden! ("unchecked E.") _Quelle: [Java ist auch eine Insel - 6.3 Die Klassenhierachie der Fehler][javainsel02]_ --- # Runtime Exceptions * Können an vielen Stellen auftreten * Beispiele: * `ArrayIndexOutOfBoundsException` * `NullPointerException` * `ArithmeticException` * **Können** gefangen werden (kein try-catch erzwungen) * → sind also "Unchecked" Exceptions * Bei Auftreten einer `RuntimeException` wird das Programm beendet (wenn kein `try` - `catch` verwendet wurde) * Werden meist von der Konsole nicht erkannt um zu warnen. Was sollte meine Main Methode daher am Besten tun? Einen Try Catch Block definieren um Runtime Exceptions wenigstens erkennen zu können! --- # Checked Exceptions * Sind NICHT von RuntimeException abegeleitet (sondern z.B. von Exception) * MÜSSEN in der MethodenSignatur deklariert werden, wenn die Methode eine C.E. wirft * MÜSSEN vom Aufrufer in einem try-catch Block aufgerufen werden! * Der Aufrufer kann also nicht sagen, dass er "überrascht" wurde (:-) Die Meinungen zu Checked Exceptions sind geteilt: Sie werden mühsam beim Programmieren auf Grund der vielen Try-Catch Blöcke, die eigentlich dem Sinn von Exceptions ("Programmieren für den Gut-Fall") widersprechen. Sie müssen überlegen, ob Sie Ihre Exceptions von RuntimeException ableiten (kein Try-Catch nötig) oder nicht. --- # Exceptionhandling in Java 1: Behandeln einer checked Exception ```java try { // Aufruf einer Methode die in ihrer Signatur " throws XYZException" stehen hat // z.B. Vehicle createVehicle(VehicleGroups i) throws IllegalFactoryArgument } catch ( XYZException e ) { // Exception LOGGEN!!! // Programmcode zum Behandeln der Ausnahme: kann Fehler geheilt werden? // wenn Fehler nicht beseitigt: Exception nach oben reichen: throw e; } // Es geht ganz normal weiter, denn die Ausnahme wurde behandelt ``` * Evtl. `finally`-Block falls aufgeräumt werden muss vor dem return. --- # `finally` Block * Wird **immer** ausgeführt! Egal, ob ein Fehler aufgetreten ist oder nicht * Auch bei `return`, `break`, `continue` * Optional * Stehen hinter `catch`-Blöcken * `try` - `finally` ist auch möglich * Meist zum Schliessen offener Ressourcen verwendet! --- # Alternativ: Automatisches Ressourcen Management .left-column50[ ### Alt ```java InputStream in = ClassLoader .getSystemResourceAsStream( "EastOfJava.txt" ); final Scanner res = new Scanner(file); try { System.out.println(res.nextLine()); } finally { res.close(); } ``` ] .right-column50[ ### Neu ```java try-with-resources statement InputStream in = ClassLoader .getSystemResourceAsStream( "EastOfJava.txt" ); try(Scanner res = new Scanner(in)) { System.out.println(res.nextLine()); } ``` ]
Objekte die java.lang.AutoCloseable, (darunter java.io.closable) implementieren, werden automatisch geschlossen bei einer Exception im try Block. _Quelle: [Java ist auch eine Insel - 6.6 Automatisches Ressourcen-Management][javainsel01]_ --- # Exceptionhandling in Java 2: Selber Checked Exception deklarieren mit`throws` * Androhung einer Exception für den Aufrufer * Im Fehlerfall: Abbruch der Methode, Fehlerbehandlung durch die aufrufende Methode * Angabe im Methodenkopf: ```java public void printData(URl url) throws MalformedURLException, IOException { // ... Programmcode hier // throw new MalformedURLException(); } ``` * Aufrufer wird zu try-catch Block gezwungen * Wenn wir stattdessen eine RuntimeException werfen, brauchen wir das nicht deklarieren und der Aufrufer muss keinen try-catch Block machen. Dafür kann ihn unsere Exception "überraschen". --- # Exceptionhandling in Java 3: Exceptions auslösen mit `throw` * Schlüsselwort `throw` * Beispiel: ```java if(age < 0) { throw new IllegalArgumentException("Ungültiges Alter: " + age); } ``` * Wird eine neue Exception mit `throw` geworfen, so muss der Exception-Typ im Methoden-Kopf erwähnt werden (Ausnahme `RuntimeException`s): ```java public void createFile() throws IOException{ // ... throw new IOException("Datei nicht vorhanden"); // ... } ``` --- # Exceptionhandling in Java 4: Eigene Exception definieren * "Checked": Die Klasse muss von `Exception` oder Sub-Klasse von `Exception` erben * "UnChecked, RuntimeE." : die Klasse muss von `Error` oder `RuntimeException` erben * Klasse kann dann als Exception verwendet werden * Üblicherweise zwei Konstruktoren: * Standard-Konstruktor * String-Konstruktor, um Fehlermeldung zu speichern --- # Beispiel einer eigenen "checked" Exception 1. Exception ableiten: package core.exceptions 2. Exception werfen: package extensions.implementationsCustomerA.VehicleFactory 3. Exception fangen und behandeln; package extensions.implementationsCustomerA.Main... https://gitlab.mi.hdm-stuttgart.de/kriha/se2_examples/-/blob/master/src/main/java/se2examples --- # Effekte der Exception-Klassenhierarchie ```java ... catch (Exception e){ ... } ``` * Fängt alle Fehler → gleiche Ausnahmebehandlung * Warum? Wo macht der Code Sinn? Denken Sie an RuntimeExceptions.. * Vorteile? * Nachteile? --- # Klassenhierarchie * "Ober-Exceptions" behandeln auch "Sub-Exceptions" * z.B. `NotSerializiableException`s können auch von `IOException`s behandelt werden * Reihenfolge der `catch`-Anweisungen spielt eine Rolle! --- # Was funktioniert? .left-column50[ ```java try { // Programmcode, der eine // Ausnahme ausführen kann } catch(NotSerializibleException e) { // ... } catch(IOException e) { // ... } ``` ] .right-column50[ ```java try { // Programmcode, der eine // Ausnahme ausführen kann } catch(IOException e) { // ... } catch(NotSerializibleException e) { // ... } ``` ] --- # Fangen mehrerer Fehlertypen ```java try { // Programmcode, der eine Ausnahme ausführen kann } catch ( NumberFormatException e ) { // ... } catch ( IOException e ) { // ... } catch ( Exception e ) { // ... } ``` --- # Multi-Catch * Seit Java 7 ```java try { //... } catch(ExceptionTyp1 | ExceptionTyp2 | ... | ExceptionTypN e) { //... } ``` * Fasst gleiche Exception-Behandlungen zusammen --- # Exception Besonderheiten * Bei überschriebenen Methoden: * selbe Ausnahmen wie Oberklasse * Ausnahmen spezialisieren * weglassen * Bei Rückgaben und Exceptions * Bei Rückgaben und `finally` --- # Architekturüberlegungen * Wie verhält sich der Aufrufer bei checked exceptions? * Wie verhält sich der Aufrufer bei runtime exceptions? * Wann verwende/werfe ich welche Exceptions? * Was ist ABSOLUT wichtig bei Exceptions? --- # Wie verhält sich der Aufrufer bei checked exceptions?
--- # Wie verhält sich der Aufrufer bei runtime exceptions?
--- # Wie verhält sich der Werfer?
--- # Wichtige TIPPS
--- # Weitere Links * Oracle: The Java™ Tutorials - Lesson: Exceptions https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html * falkhausen.de: Exception Hierarchie http://www.falkhausen.de/Java-8/java.lang/Exceptions.html * guru99.com: Java Exception Handling https://www.guru99.com/java-exception-handling.html --- class: center, middle # Fragen? [javainsel01]: http://openbook.rheinwerk-verlag.de/javainsel/javainsel_06_006.html [javainsel02]: http://openbook.galileocomputing.de/javainsel/javainsel_06_003.html