• Keine Ergebnisse gefunden

Programmiertechnik Ausnahmen

N/A
N/A
Protected

Academic year: 2022

Aktie "Programmiertechnik Ausnahmen"

Copied!
28
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Programmiertechnik Ausnahmen

Prof. Dr. Oliver Haase

(2)

Motivation

public class Excep1 {

public void doYourJob() {

Scanner scanner = new Scanner(System.in);

System.out.print("a: ");

int a = scanner.nextInt();

System.out.print("b: ");

int b = scanner.nextInt();

System.out.println("a / b = " + a/b);

}

public static void main(String[] args) { Excep1 instance = new Excep1();

instance.doYourJob();

System.out.println("Job done.");

} }

(3)

Motivation

java Excep1 a: 15

b: 3

a / b = 5 Job done.

Konsole

 Anwendungsbeispiel 1:

java Excep1 a: 15

b: 0

java.lang.ArithmeticException: / by zero at Excep1.doYourJob(Excep1.java:7)

Konsole

 Anwendungsbeispiel 2:

(4)

Motivation

 Unter bestimmten Umständen kann das Programm nicht

ordnungsgemäß beendet werden, sondern liefert einen Fehler und bricht ab.

 Es gibt eine Vielzahl möglicher Fehlerquellen:

 arithmetische Operationen (Division durch 0, …)

 Zugriff auf Datei, die nicht existiert

 Schreibzugriff auf schreibgeschützte Datei

 Festplattenschaden

 Programm lädt Daten aus dem Internet herunter, Kommunikationsverbindung bricht ab.

 …

Diese Vorlesung handelt davon, wie man in Java-Programmen mit solchen Fehlersituationen umgeht.

(5)

Fehlerbehandlungsmethoden

 Moderne Programmiersprachen, wie z.B. C++ und Java, verwenden Ausnahmen (exceptions) für die Fehlerbehandlung.

 In älteren Programmiersprachen (z.B. in C) verwendet man die Funktionsrückgabewerte, um fehlerhafte Funktionsausführung anzuzeigen  integrierte Fehlerbehandlung

 Das Fehlschlagen einer Funktion wird dabei üblicherweise durch einen negativen Rückgabewert angezeigt.

(6)

integrierte Fehlerbehandlung

public class Excep2 {

public int doYourJob() {

Scanner scanner = new Scanner(System.in);

System.out.print("a: ");

int a = scanner.nextInt();

System.out.print("b: ");

int b = scanner.nextInt();

if ( b == 0 ) return -1;

System.out.println("a / b = " + a/b);

return 0;

 C-Stil Fehlerbehandlung in Java:

(7)

integrierte Fehlerbehandlung

public static void main(String[] args) { int ret;

Excep2 instance = new Excep2();

if ( ( ret = instance.doYourJob() ) < 0 ) System.out.println("Fehlercode: " + ret);

else

System.out.println("Job done.");

} }

java Excep2 a: 15

b: 0

Fehlercode: -1

Konsole

(8)

Diskussion

 Integrierte Fehlerbehandlung hat mehrere Nachteile:

 verschiedene Fehlerwerte für verschiedene Funktionen, manchmal bedeutet 0 Fehler, manchmal -1, manchmal jeder negative Wert…

 Aufrufer muss wissen, welchen Wert Funktion im Fehlerfall liefert

 Fehler sollten die Ausnahme sein  unnatürlich, den Rückgabewert einer Funktion dem Fehlerfall zu widmen

 Fehlerbehandlung integriert in "regulären" Code  schwer lesbar

 Wenn Funktion tatsächlich einen Wert liefern soll, muss entweder dieser Wert oder der Fehlercode innerhalb eines

Referenztypparameters zurückgegeben werden.

(9)

Fehlercode als Referenzparameter

Beispiel: Angenommen, die Methode doYourJob druckt das Ergebnis der Divsion a/b nicht aus, sondern liefert es als Ergebniswert zurück:

public class Excep3 {

public int doYourJob(int[] error) {

Scanner scanner = new Scanner(System.in);

System.out.print("a: ");

int a = scanner.nextInt();

System.out.print("b: ");

int b = scanner.nextInt();

if ( b == 0 ) { error[0] = -1;

return -1;

}

error[0] = 0;

return a/b;

(10)

integrierte Fehlerbehandlung

public static void main(String[] args) { Excep3 instance = new Excep3();

int[] error = new int[1];

int ret = instance.doYourJob(error);

if ( error[0] == -1 )

System.out.println("Fehlercode: " + error[0]);

else {

System.out.println("a / b = " + ret);

System.out.println("Job done.");

} } }

Alternative: Statt ein Feld zu verwenden könnte man eine Klasse definieren, die eine int-Komponente für den Errorcode enthält.

Fazit: Funktioniert, aber mühsam, unnatürlich und fehleranfällig…

(11)

Ausnahmen/Exceptions

 Trennung von regulärem Code und Fehlerbehandlung.

 Wenn Ausnahmesituaton eintritt – z.B. Division durch 0 – wird ein Exception-Objekt erzeugt und mit Informationen zur Fehlerursache und zum Ort des Auftretens initialisiert.

 Diese Informationen können über geeignete Instanzmethoden abgerufen werden.

 Exceptions werden nicht als reguläre Methodenrückgabewerte

propagiert, sondern über einen speziellen Exception-Mechanismus.

(12)

Ausnahmen/Exceptions

 In Java ist jedes Exception-Objekt eine Instanz der Klasse java.lang.Exception, oder einer Subklasse davon.

 Die Fehlerursache kann mit der Instanzmethode

public String getMessage() abgerufen werden.

 Der Ort des Auftretens kann mit der Instanzmethode

public String printStackTrace() abgerufen werden.

java Excep1 a = 15

b = 0

java.lang.ArithmeticException: / by zero at Excep1.doYourJob(Excep1.java:10)

Konsole

Exception-Klasse

getMessage()

(13)

Abfangen von Exceptions

 Wenn eine Ausnahmesituation auftritt, wird eine Exception (Ausnahme) geworfen ("to throw an exception").

 Exceptions können im Programm abgefangen werden ("to catch an exception"), um

 Abstürze zu vermeiden

 geeignete Fehlerbehandlung durchzuführen, etwa

Meldung ausgeben (z.B. in einem geeigneten Fenster)

Aufräumen bevor das Programm ordentlich terminiert wird.

(14)

Abfangen von Exceptions

 In Java geschieht dies durch eine Kombination von try und catch Anweisungen:

 Anweisungen, die fehlschlagen können, werden mit try eingeklammert;

 Die Fehlerbehandlung folgt in 1 oder mehreren catch-Blöcken.

(15)

Abfangen von Exceptions

 Beispiel:

public void doYourJob() {

Scanner scanner = new Scanner(System.in);

System.out.print("a: ");

int a = scanner.nextInt();

System.out.print("b: ");

int b = scanner.nextInt();

try {

System.out.println("a/b = " + a/b);

} catch(ArithmeticException e) {

System.out.println("Wir haben da ein Problem: "

+ e.getMessage());

System.out.println(

"Das haetten Sie nicht tun sollen...");

}}

(16)

Abfangen von Exceptions

java Excep4 a: 15

b: 0Wir haben da ein Problem: / by zero Das haetten Sie nicht tun sollen...

Konsole

Beachte: Das Programm terminiert nicht mehr automatisch, nachdem die Exception geworfen wurde!

(17)

Beispiel – Daten aus Datei lesen

 Berechnung des arithmetischen Mittelwerts einer Menge ganzer Zahlen.

 Die Zahlen stehen in einer Datei vals.txt, und zwar genau eine Zahl pro Zeile, gefolgt von einem Zeilenumbruch.

 Beispiel:

24 10

Inhalt der Datei vals.txt

(Mittelwert: 1.75)

(18)

Beispiel – Daten aus Datei lesen

 Die Lösung in Java benötigt 2 Klassen aus dem Paket java.io, nämlich FileReader und BufferedReader.

 Eine Instanz der Klasse FileReader repräsentiert eine zum Lesen geöffnete Datei. Mit Hilfe der folgenden Zeile wird ein Objekt f vom Typ FileReader erzeugt, das Daten aus der Datei vals.txt

lesen kann:

FileReader f = new FileReader("vals.txt");

Beachte: Mit einem FileReader-Objekt kann man eine Datei nur zeichenweise einlesen.

(19)

Beispiel – Daten aus Datei lesen

 Instanzen der Klasse BufferedReader erlauben, Dateien

zeilenweise einzulesen. Die folgende Anweisung erzeugt ein solches Objekt unter Verwendung des zuvor erzeugten FileReader-

Objekts:

BufferedReader b = new BufferedReader(f);

 Beide Anweisungen können zusammengefasst werden:

BufferedReader b =

new BufferedReader(new FileReader("vals.txt"));

 Damit sieht der 1. Lösungsversuch wie folgt aus:

(20)

Beispiel – Daten aus Datei lesen

import java.io.*;

public class Mittelwert {

private static int anzahl = 0;

public static int parse(String s) { anzahl++;

return Integer.parseInt(s);

}

Fortsetzung auf nächster Folie…

(21)

Beispiel – Daten aus Datei lesen

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

System.out.print("Dateiname: ");

String fileName = scanner.next();

BufferedReader datei =

new BufferedReader(new FileReader(fileName));

double mittel = 0.0;

String line = datei.readLine();

while ( line != null ) { mittel += parse(line);

line = datei.readLine();

}

mittel /= anzahl;

System.out.println("Mittelwert: " + mittel);

}

(22)

Beispiel – Daten aus Datei lesen

Aber: Der Versuch, die Klasse zu übersetzen

(javac Mittelwert.java) liefert folgende Fehlermeldung:

Mittelwert.java:16: unreported exception

java.io.FileNotFoundException; must be caught or declared to be thrown

new BufferedReader(new FileReader(fileName));

^

Mittelwert.java:18: unreported exception

java.io.IOException; must be caught or declared to be thrown

String line = datei.readLine();

^

Mittelwert.java:21: unreported exception

java.io.IOException; must be caught or declared to be thrown

Konsole

(23)

Beispiel – Daten aus Datei lesen

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

System.out.print("Dateiname: ");

String fileName = scanner.next();

BufferedReader datei =

new BufferedReader(new FileReader(fileName));

double mittel = 0.0;

String line = datei.readLine();

while ( line != null ) { mittel += parse(line);

line = datei.readLine();

}

mittel /= anzahl;

System.out.println("Mittelwert: " + mittel);

}

FileNotFoundException möglich

IOException möglich

(24)

Beispiel – Daten aus Datei lesen

Mögliche Lösung: throws-Klausel im Kopf der main-Methode:

import java.io.*;

import java.util.Scanner;

public class Mittelwert2 {

private static int anzahl = 0;

public static int parse(String s) {

} public static void main(String[] args)

throws FileNotFoundException, IOException { ...

}}

Effekt: Reicht die Exception durch zur aufrufenden Methode, in

(25)

Beispiel – Daten aus Datei lesen

java Mittelwert2 Datei: bals.txt

Exception in thread "main" java.io.FileNotFoundException:

bals.txt (Das System kann die angegebene Datei nicht finden)

at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileReader.<init>(Unknown Source)

at Mittelwert.main(Mittelwert2.java:16) Konsole

(26)

Beispiel – Daten aus Datei lesen

Alternative Lösung: Exceptions abfangen:

public static void main(String[] args) { BufferedReader datei = null;

Scanner scanner = new Scanner(System.in);

boolean success;

do {

System.out.println("Dateiname: ");

String fileName = scanner.next("Dateiname: ");

System.out.println("Datei: " + fileName);

try {

datei =

new BufferedReader(new FileReader(fileName));

success = true;

}

catch ( FileNotFoundException e ) { success = false;

(27)

Beispiel – Daten aus Datei lesen

double mittel = 0.0;

try {

String line = datei.readLine();

while ( line != null ) { mittel += parse(line);

line = datei.readLine();

}

mittel /= anzahl;

System.out.println("Mittelwert: " + mittel);

} catch ( IOException e ) {

System.out.println("Fehler beim Einlesen");

System.exit(0);

}}

(28)

Have an

exceptionally nice

cup of coffee!

Referenzen

ÄHNLICHE DOKUMENTE

Wird ein Objekt eines bestimmten Typs erzeugt, so wird dieses Objekt manchmal als eine Instanz dieses Typs bezeichnet (obwohl eine Instanz eines Typs nicht mit einer Instanz

 Bisher: Objekte sind Sammlungen von Daten (Beispiel: Klasse Adresse für Adressbuchverwaltung)..  Idee: Erweitere Objekte um Verhalten

Mit Hilfe einer toString - Methode kann ein derart erzeugtes Objekt (in der main -Methode) auf dem Bildschirm ausgegeben werden. Welche der Programme sind fehlerhaft und

2. Falls Auswertung false ergibt, wird die Schleife beendet 3. Falls Auswertung true ergibt, wird. a)

 innere Klasse: Die Klasse wird innerhalb einer anderen Klasse definiert..!. (Beachte: der untere, leere Teil wird später

 Eine Methode kann Parameter (Argumente) enthalten, die beim Aufruf durch Werte ersetzt werden..  Eine Methode kann ein

• Sollte der Platz zwischen den Aufgaben für die Beantwortung nicht ausreichen, benutzen Sie bitte die Blattrückseiten mit vermerk der Aufgabennummer.. • Achten Sie auf

Wenn ein Metall in Reichweite des Magnetfeldes sich befindet, entstehen in dem metallischen Objekt Wirbelströme, welche so gerichtet sind, dass sie der Ursache (das