• Keine Ergebnisse gefunden

Ausnahmen und deren Behandlung

N/A
N/A
Protected

Academic year: 2021

Aktie "Ausnahmen und deren Behandlung"

Copied!
49
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Ausnahmen und deren Behandlung

OOPM, Ralf Lämmel

Schon mal einen Blue

Screen gesehen?

(2)

Beispiele für Ausnahmesituationen

Programmfehler

“precondition failed”

Unzulässige Nutzereingabe

“bad url”

Nichtverfügbarkeit von Ressourcen

“connection lost”

Verausgabung von Ressourcen

“stack overflow”

(3)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Verhalten eines Programmes bei unzulässigen Eingaben

3

$ java Program 3 4 3 + 4 = 7

$ java Program 3

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1 at Program.main(Program.java:12)

$ java Program 3 vier

Exception in thread "main" java.lang.NumberFormatException: For input string: "vier"

at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:447)

at java.lang.Integer.parseInt(Integer.java:497) at Program.main(Program.java:12)

Können wir uns bessere

Fehlermeldungen vorstellen?

(4)

Verhalten des Programmes mit Ausnahmebehandlung

$ java Program 3 4 3 + 4 = 7

$ java Program 3

Incorrect number of arguments

$ java Program 3 vier

Argument(s) not a number

(5)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Quellen für Ausnahmesituationen im Programm

5 public class Program {

public static void main(String[] args) { int value1 = Integer.parseInt(args[0]);

int value2 = Integer.parseInt(args[1]);

int sum = value1 + value2;

System.out.println(value1 + " + " + value2 + " = " + sum);

} }

Feldzugriff kann scheitern

Konvertierung in Zahl kann scheitern

Illustrationen für Ausnahmebehandlung siehe Repository: idioms.errorhandling

Haben Sie noch eine weitere Idee

für eine Ausnahmesituation?

(6)

Ansatz der Ausnahmebehandlung

public class Program {

public static void main(String[] args) { int value1 = Integer.parseInt(args[0]);

int value2 = Integer.parseInt(args[1]);

int sum = value1 + value2;

System.out.println(value1 + " + " + value2 + " = " + sum);

} }

Teste dass args.length == 2

Behandle nichterfolgreiche Konvertierung

(7)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Allgemeine Fragestellungen

1. Was ist ein Fehler bzw. eine Ausnahme?

2. Wie wissen wir, dass ein Fehler bzw. eine Ausnahme auftritt?

3. Wie weiß ein Programm dies?

4. Wie reagiert ein Programm auf einen Fehler bzw. eine Ausnahme?

5. Kann das Programm sich erholen?

7

(8)

Fehler

Definition: ein unerlaubter Programmzustand Beispiel: das Beispielprogramm darf nicht in

dem Zustand sein, dass es in die main-Funktion eintritt wobei nur 1 Eingabewert ansteht.

Naives Modell der Fehlervermeidung: Die Spezifikation von Methoden, Klassen und Programmen definiert was erlaubte

Programmzustände sind. Jede Verwendung der Methoden, Klassen und Programmen wird im Voraus auf die Einhaltung der Spezifikation überprüft.

Der Begriff ist

hochgradig überladen.

(9)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Ziele der Fehlerbehandlung

Vermeidung von inkonsistentem Verhalten

Rückkehr zu früherem, sicherem Programmpunkt Kontrollierte Beendung des Programmes

Sicherung von Ergebnissen

Ausgabe von hilfreichen Fehlermeldungen

9

(10)

Techniken zur Fehlerbehandlung

Keine Behandlung

Terminierung des Programmes

Verwendung eines globalen Fehlerflags

Verwendung eines speziellen Rückgabewertes Vereinbarung einer speziellen Funktion

Verwendung von Transaktionsmechanismen

Ausnahmebehandlung mit try/catch

(11)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Techniken zur Fehlerbehandlung

Keine Behandlung

Terminierung des Programmes

Verwendung eines globalen Fehlerflags

Verwendung eines speziellen Rückgabewertes Vereinbarung einer speziellen Funktion

Verwendung von Transaktionsmechanismen Ausnahmebehandlung mit try/catch

11

(12)

Verwendung eines globalen Fehlerflag

Wir “erfinden” java.lang.Integer.error.

Wir ignorieren das Problem der Feldgröße im folgenden.

int value1 = Integer.parseInt(args[0]);

boolean error = Integer.error;

int value2 = Integer.parseInt(args[1]);

error |= Integer.error;

if (!error) {

int sum = value1 + value2;

System.out.println(value1 + " + " + value2 + " = " + sum);

}

else {

System.err.println("Argument(s) not a number");

System.exit(-1);

}

Abfrage des Fehlerflags nach

jedem Aufruf

Das Abfragen des Flags kann leicht

vergessen werden.

(13)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Techniken zur Fehlerbehandlung

Keine Behandlung

Terminierung des Programmes

Verwendung eines globalen Fehlerflags

Verwendung eines speziellen Rückgabewertes Vereinbarung einer speziellen Funktion

Verwendung von Transaktionsmechanismen Ausnahmebehandlung mit try/catch

13

(14)

Verwendung eines speziellen Rückgabewertes

Wir ändern den Ergebnistyp von parseInt von int nach Integer.

(Integer ist ein Referenztyp für int.) Wir interpretieren null als Fehler.

Integer value1 = Integer.parseInt(args[0]);

boolean error = value1 == null;

Integer value2 = Integer.parseInt(args[1]);

error |= value2 == null;

if (!error) {

int sum = value1 + value2;

System.out.println(value1 + " + " + value2 + " = " + sum);

}

else {

System.err.println("Argument(s) not a number");

System.exit(-1);

}

Interpretiere null als Fehler

Fehler können weiterhin übersehen werden oder der Fehlerwert kann fehlinterpretiert werden. Auch verlangt

diese Technik häufig Typänderungen.

(15)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Techniken zur Fehlerbehandlung

Keine Behandlung

Terminierung des Programmes

Verwendung eines globalen Fehlerflags

Verwendung eines speziellen Rückgabewertes Vereinbarung einer speziellen Funktion

Verwendung von Transaktionsmechanismen Ausnahmebehandlung mit try/catch

15

(16)

Vereinbarung einer speziellen Funktion

Illustration für Cobol; Vereinbarung eines Fehlerparagraphen für bestimmte Dateifehler.

DECLARATIVES.

HANDLE-FILE-ERRORS SECTION.

USE AFTER ERROR ON ACCOUNT-FILE.

HANDLE-ACOUNT-ERROR.

MOVE “ACOUNT” TO PANIC-RESOURCE.

MOVE “FILE ERROR” TO PANIC-HEADER.

MOVE FILE-STATUS TO PANIC-CODE.

GO TO PANIC-STOP.

END-DECLARATIVES.

Diese Technik verlangt Sprachunterstützung.

Ausnahmen (siehe nachfolgend) sind allgemeiner.

(17)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Techniken zur Fehlerbehandlung

Keine Behandlung

Terminierung des Programmes

Verwendung eines globalen Fehlerflags

Verwendung eines speziellen Rückgabewertes Vereinbarung einer speziellen Funktion

Verwendung von Transaktionsmechanismen Ausnahmebehandlung mit try/catch

17

(18)

Ausnahmebehandlung mit try/catch

try {

int value1 = Integer.parseInt(args[0]);

int value2 = Integer.parseInt(args[1]);

int sum = value1 + value2;

System.out.println(value1 + " + " + value2 + " = " + sum);

}

catch (NumberFormatException e) {

System.err.println("Argument(s) not a number");

System.exit(-1);

}

(19)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Der OO-Ansatz: Ausnahmen

Ausnahme: ein Ereignis während der

Ausführung des Programms welches zur Unterbrechung des regulären Ablaufs führt.

Java-Repräsentation einer Ausnahme:

Objekte der Klasse Throwable oder deren Unterklassen.

Werfen einer Ausnahme: Bei der Feststellung eines Fehlers wird (vom Laufzeitsystem oder vom Programm) ein Ausnahmeobjekt

konstruiert und an das Laufzeitsystem zur Behandlung übergeben.

19

(20)

Vom Programm geworfene Ausnahme

public class Program {

public static void main(String[] args) {

throw new RuntimeException("Don’t call main!");

}

} Ein konkreter

Ausnahmetyp

Parameter für

Diagnose.

(21)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Vordefinierte Ausnahmeklassen

21

Ausnahmen werden durch Klassen in einer

Vererbungshierarchie

organisiert.

(22)

Wichtige Unterklassen von Throwable

Error Klasse und Unterklassen: Kritischer Fehler von dem kaum zu erwarten ist, dass die Applikation ihn behandeln kann.

Virtual Machine Error

Exception Klasse und Unterklassen: Mögliche

Ausnahme in der “normalen” Programmausführung.

Solche Ausnahmen können behandelt werden.

IOException

NullPointerException

(23)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Ausnahmen des Laufzeitsystems

IndexOutOfBoundsException: Der Index bei einem Feldzugriff ist nicht im zulässigen Bereich.

ArrayStoreException: Der Typ des Objektes bei einem schreibenden Feldzugriff ist nicht zulässig.

NullPointerException: Ein Feldzugriff oder ein Methodenaufruf auf “null” anstatt einem Objekt.

SecurityException: Der Security Manager weist einen Verstoss gegen die Sicherheitspolitik ab.

....

23

(24)

Sprachunterstützung für Ausnahmebehandlung

try {

... // Anweisungen die Ausnahmen werfen könnten }

catch(AusnahmeTyp name) {

... // Anweisungen welche die Ausnahme behandeln

}

(25)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Ausnahmebehandlung mit try/catch

25

try {

int value1 = Integer.parseInt(args[0]);

int value2 = Integer.parseInt(args[1]);

int sum = value1 + value2;

System.out.println(value1 + " + " + value2 + " = " + sum);

}

catch (NumberFormatException e) {

System.err.println("Argument(s) not a number");

System.exit(-1);

}

(26)

Sprachunterstützung für Ausnahmebehandlung einschließlich des finally-Blockes

Der catch-Block ist anwendbar für eine Ausnahme a wenn der Typ von a zuweisungskompatibel mit AusnahmeTyp ist.

Der finally-Block wird auch für den Fall ausgeführt, dass der catch-Block nicht anwendbar ist oder der catch oder try-Block continue oder break benutzt.

try {

... // Anweisungen

} catch (AusnahmeTyp name) { ... // Anweisungen

} finally {

... // Anweisungen }

try-Block

finally- Block

catch- Block

Keine Ausnahme

Ausnahme

(27)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Mehrere Catch-Klauseln

27

try {

} catch (AusnahmeTyp1 name1) {

} catch (AusnahmeTyp2 name2) {

} finally {

}

Klauseln werden in Definitionsreihefolge geprüft.

Speziellere Ausnahmetypen sind zuerst anzugeben!

(28)

Ein Tabu-Idiom

Konsumiert alle Ausnahmen.

Behandelt keine Ausnahmen.

Verursacht eventuell schwierige Folgefehler.

try { ...

}

catch (Exception x) { }

(29)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Propagierung von Ausnahmen

Innerhalb von Hierarchien von Throw-Blöcken zum unmittelbar umfassenden throw-Block Im Aufrufkeller

zum nächsten Aufruf mit einem Handler

29

(30)

Illustration für Propagierung

public class Program {

public static void a() { b(); } public static void b() { c(); } public static void c() {

throw new RuntimeException("Safe Our Souls!");

}

public static void main(String[] args) { try {

a();

} catch (RuntimeException e) { e.printStackTrace();

} }

}

java.lang.RuntimeException: Safe Our Souls!

at Program.c(Program.java:9) at Program.b(Program.java:6) at Program.a(Program.java:3)

at Program.main(Program.java:13)

(31)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

java.lang.RuntimeException: Safe Our Souls!

at Program.c(Program.java:9) at Program.b(Program.java:6) at Program.a(Program.java:3)

at Program.main(Program.java:13)

“Stack trace”

31

Ausnahmetyp Parameter

der Ausnahme

Methode der

Behandlung

(32)

Aufrufkeller und Ausnahmebehandlung (für ein neues Szenario)

main

Methode mit Exception handler

Methode ohne Exception handler

Methode mit Ausnahme

Methodenaufruf Methodenaufruf Methodenaufruf

Methode wirft Ausnahme

Methode reicht Ausnahme durch

Methode behandelt Ausnahme

Methode ist

“unbehelligt”

(33)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Wichtige Regeln

Konsumiere nur die Ausnahmen, die Du auch behandelst (behandeln kannst).

Wenn sich eine Ausnahme als nicht behandelbar herausstellt, nachdem sie bereits abgefangen

wurde, dann muss sie erneut geworfen werden.

Verwende Klassenvererbung um ein System von Ausnahmen in einer Hierarchie zu organisieren.

33

(34)

Wann sollte man eine Ausnahme werfen anstatt einfach zurückzukehren?

Pro Ausnahmewurf

Es handelt sich um eine wirkliche Ausnahmesituation.

Der Aufrufer sollte das Problem nicht ignorieren können.

Die Klasse wäre sonst instabil oder inkonsistent.

Con Ausnahmewurf

Das Problem kann allgemein lokal behoben werden.

(35)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Ein weiteres Beispiel:

Abhebung vom Konto

Ausnahmesituationen Betrag ist negativ

IllegalArgumentException Betrag überzieht Konto

OverdraftException

35

Anwendungsspezifisches Problem, welches behandelt werden sollte.

Grundlegendes Problem (als Folge eines Bedienfehlers oder

einer Vertragsverletzung)

(36)

Abhebung vom Konto mit Überziehungskontrolle

/**

* Withdraw some money from account.

* Refuse negative amounts as nonsense.

* Throw an exception if an attempt is made to overdraw.

*/

public void withdraw(float amount) {

// Precondition if (amount < 0)

throw new IllegalArgumentException();

if (balance < amount)

throw new OverdraftException();

balance -= amount;

}

Vordefinierte Ausnahmeklasse

Programm-definierte

Ausnahmeklasse

(37)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Programm-definierte Ausnahmenklassen

37

Unterklassen von Exception Konstruktoren

Standardkonstruktor

Konstruktor mit String-Parameter (“Fehlermeldung”) Weiterer Zustand

Daten für Handler

public class OverdraftException

extends RuntimeException { }

Für

fortgeschrittene

Szenarien

(38)

Verwendung von

Zusicherungen vs. Ausnahmen

public void withdraw(float amount) { // Precondition

assert !( amount < 0

|| balance < amount);

balance -= amount;

}

Verletzten der

Vorbedingung führt zum Werfen einer Ausnahme

AssertionError.

(39)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Verwendung von

Zusicherungen vs. Ausnahmen

39

public void withdraw(float amount) {

// Precondition if (amount < 0)

throw new IllegalArgumentException();

if (balance < amount)

throw new OverdraftException();

balance -= amount;

}

Spezifischere Ausnahme als AssertionError

Wir werden zeigen, dass wir den Aufrufer zur Behandlung

zwingen wollen und können!

(40)

Zwang zur Ausnahmebehandlung

Gedankenexperiment

Was wäre wenn wir Aufrufer von “withdraw” zur Ausnahmebehandlung “ermutigen” (“erzwingen”) wollen -- soweit es den Versuch der

Kontenüberziehung angeht?

Ein solcher Versuch ist schließlich eine

Ausnahmesituation, auf welche das Programm

vorbereitet sein sollte.

(41)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Wir wollen dieses Programm verbieten.

41

public static void transfer( Account from , Account to

, float amount) { to.deposit(amount);

from.withdraw(amount);

}

Der Compiler (das Typsystem) soll den

Programmierer zwingen, den möglichen Fehler zu

behandeln.

(42)

Verwendung geprüfter Ausnahmen

Ungeprüfte Ausnahmen

Sind von RuntimeException abgeleitet

Müssen nicht in Methodensignatur spezifiziert werden Gelten eher als nicht reparierbar

Geprüfte Ausnahmen

Sind nicht von RuntimeException abgeleitet

Müssen in Methodensignatur spezifiziert werden Sollten von der Anwendung behandelt werden

public class OverdraftException

extends RuntimeException { }

Änderung unserer

ursprünglichen

Ausnahmeklasse

(43)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Dieses Programm wird abgewiesen.

43

public static void transfer( Account from , Account to

, float amount) { to.deposit(amount);

from.withdraw(amount);

}

Wir müssen die Ausnahme

OverdraftException entweder

deklarieren oder behandeln.

(44)

Eine Behandlung innerhalb der Methode transfer ist nicht offensichtlich.

public static void transfer( Account from , Account to

, float amount) { try {

from.withdraw(amount);

to.deposit(amount);

}

catch (OverdraftException o) { // ... but what to do?

}

}

(45)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Die Behandlungspflicht ergeht an Aufrufer.

45

public static void transfer( Account from , Account to , float amount) throws OverdraftException {

from.withdraw(amount);

to.deposit(amount);

}

Der Compiler (das Typsystem) soll den Programmierer wenigstens dazu zwingen, die

Ausnahme zu deklarieren.

Die mögliche

Ausnahme wird

explizit deklariert.

(46)

Deklaration von werfbaren Ausnahmen

/**

* Withdraw some money from account.

* Refuse negative amounts as nonsense.

* Throw an exception if an attempt is made to overdraw.

*/

public void withdraw(float amount)

throws OverdraftException {

// Precondition if (amount < 0)

throw new IllegalArgumentException();

if (balance < amount)

throw new OverdraftException();

balance -= amount;

}

Der Compiler (das Typsystem) verlangt die throws-Deklaration (im Falle einer geprüften

IllegalArgumentExceptio n ist eine ungeprüfte Ausnahmeklasse und muss deswegen nicht

deklariert werden.

(47)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Geprüft oder ungeprüft?

47

Sun´s (Oracle’s?) guideline: If a client can reasonably be

expected to recover from an exception, make it a checked

exception. If a client cannot do anything to recover from

the exception, make it an unchecked exception.

(48)

Ein Zitat zur Fehlerbehandlung

The major difference between a thing that might go wrong and a thing that cannot possibly go wrong is that when a thing that

cannot possibly go wrong goes wrong it usually turns out to be impossible to get at or repair.

Quelle:

Douglas Adams [Ada92]

(49)

(C) 2007-2018, Ralf Lämmel, Universität Koblenz-Landau

Zusammenfassung

Fehler sind unzulässige Programmzustände.

Ausnahmen sind Ereignisse, die den regulären Ablauf abbrechen.

Ausnahmen sind Objekte / Ausnahmetypen sind Klassen.

Sprachunterstützung: try, catch, finally, throw, throws Von einigen Fehler kann man sich nicht erholen.

Von gewissen Ausnahmen kann man sich erholen.

Ausblick

Probeklausur

Komplexität von (imperativen) Programmen

Modellierung von Verhalten mit Zustandsdiagrammen

Abbildung

Illustration für Propagierung

Referenzen

ÄHNLICHE DOKUMENTE

Für die Entscheidung zu einer frühen Überweisung, so Paul Emery, sollten auch Kosten-Nutzen-Überlegungen eine Rolle spielen: Für jeden Patienten, bei dem eine

Es gibt noch etliche andere Wirkstoffe, für die positive Effekte beim Reizdarmsyndrom reklamiert werden. Antibiotika kön- nen bei einer sondt therapierefraktären Diarrhö eingesetzt

Wird eine harnsäuresenkende Therapie eingeleitet, sollte – falls keine Kontraindikationen bestehen – zusätzlich Colchicin oder ein NSAR verabreicht werden, um

Bei dieser sehr wichtigen, aber leider bis anhin nur mündlich vorgestellten Studie soll sich gezeigt haben, dass Patienten zwischen 70 und 80 Jahren tatsächlich mehr von der

Man hat sich aber auch in Erinnerung zu rufen, dass eine klassische, durch eine deutlich fassbare Ves- tibularpathologie verursachte Vertigo fast immer auch schwere Angst

Oft liegt es aber gar nicht an einer echten Diuretikaresistenz, wenn die Ödeme nicht verschwinden wollen (Tabelle 2). Es könnte zum Beispiel sein, dass der Patient die Tabletten

Da ohnehin nicht mit großer Aktivität zu rechnen war, brachte ich den Waran in einem kleinen, geheizten Terrarium (Grundfläche 40X30 cm) mit einer konstanten Temperatur

Da aber die Wahrscheinlichkeit, daß der Patient die maximale Giftmenge abbekam, verschwindend klein ist, und da fernerhin die Injektion von soviel Serum nach einigen Tagen eine