Exception - an der HTWG Konstanz

Werbung
Programmiertechnik
Ausnahmen
Prof. Dr. Oliver Haase
Oliver Haase
Hochschule Konstanz
1
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.");
}
}
Oliver Haase
Hochschule Konstanz
2
Motivation
 Anwendungsbeispiel 1:
Konsole
java Excep1
a: 15
b: 3
a / b = 5
Job done.
 Anwendungsbeispiel 2:
Konsole
java Excep1
a: 15
b: 0
java.lang.ArithmeticException: / by zero
at Excep1.doYourJob(Excep1.java:7)
Oliver Haase
Hochschule Konstanz
3
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.





Oliver Haase
Hochschule Konstanz
4
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.
Oliver Haase
Hochschule Konstanz
5
integrierte Fehlerbehandlung
 C-Stil Fehlerbehandlung in Java:
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;
}
Oliver Haase
Hochschule Konstanz
6
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.");
}
}
Konsole
java Excep2
a: 15
b: 0
Fehlercode: -1
Oliver Haase
Hochschule Konstanz
7
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.
Oliver Haase
Hochschule Konstanz
8
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;
Oliver Haase
Hochschule Konstanz
9
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…
Oliver Haase
Hochschule Konstanz
10
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.
Oliver Haase
Hochschule Konstanz
11
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.
Konsole
java Excep1
Exception-Klasse
a = 15
getMessage()
b = 0
java.lang.ArithmeticException: / by zero
at Excep1.doYourJob(Excep1.java:10)
printStackTrace()
Oliver Haase
Hochschule Konstanz
12
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.
Oliver Haase
Hochschule Konstanz
13
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.
Oliver Haase
Hochschule Konstanz
14
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...");
}
Oliver Haase
Hochschule Konstanz
15
Abfangen von Exceptions
Konsole
java Excep4
a: 15
b: 0
Wir haben da ein Problem: / by zero
Das haetten Sie nicht tun sollen...
 Beachte: Das Programm terminiert nicht mehr automatisch,
nachdem die Exception geworfen wurde!
Oliver Haase
Hochschule Konstanz
16
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:
Inhalt der Datei vals.txt
2
4
1
0
(Mittelwert: 1.75)
Oliver Haase
Hochschule Konstanz
17
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.
Oliver Haase
Hochschule Konstanz
18
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 FileReaderObjekts:
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:
Oliver Haase
Hochschule Konstanz
19
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…
Oliver Haase
Hochschule Konstanz
20
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);
}
}
Oliver Haase
Hochschule Konstanz
21
Beispiel – Daten aus Datei lesen
 Aber: Der Versuch, die Klasse zu übersetzen
(javac Mittelwert.java) liefert folgende Fehlermeldung:
Konsole
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
line = datei.readLine();
^
Oliver Haase
Hochschule Konstanz
22
Beispiel – Daten aus Datei lesen
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Dateiname: ");
FileNotFoundException
String fileName = scanner.next();
möglich
BufferedReader datei =
new BufferedReader(new FileReader(fileName));
double mittel = 0.0;
String line = datei.readLine();
IOException
while ( line != null ) {
möglich
mittel += parse(line);
line = datei.readLine();
}
mittel /= anzahl;
System.out.println("Mittelwert: " + mittel);
}
}
Oliver Haase
Hochschule Konstanz
23
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
diesem Fall das Java-Laufzeitsystem, das das Programm mit einer
Fehlermeldung abbricht.
Oliver Haase
Hochschule Konstanz
24
Beispiel – Daten aus Datei lesen
Konsole
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)
Oliver Haase
Hochschule Konstanz
25
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;
}
} while ( !success );
Oliver Haase
Hochschule Konstanz
26
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);
}
Oliver Haase
Hochschule Konstanz
27
Have an
exceptionally nice
cup of coffee!
Oliver Haase
Hochschule Konstanz
28
Herunterladen