exception - Achim Bitzer

Werbung
Prof. Dr. Oliver Haase
Karl Martin Kern
Achim Bitzer
Programmiertechnik
Ausnahmen
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)
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
2/27
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.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
3/27
Ansätze zur 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.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
4/27
Integrierte Fehlerbehandlung
●
C-Stil Fehlerbehandlung in Java:
public
public class
class Excep2
Excep2 {{
public
public int
int doYourJob()
doYourJob() {{
Scanner
Scanner scanner
scanner == new
new Scanner(System.in);
Scanner(System.in);
System.out.print("a:
System.out.print("a: ");
");
int
int aa == scanner.nextInt();
scanner.nextInt();
System.out.print("b:
System.out.print("b: ");
");
int
int bb == scanner.nextInt();
scanner.nextInt();
}}
if
if (( bb ==
== 00 ))
return
return -1;
-1;
System.out.println("a
System.out.println("a // bb == "" ++ a/b);
a/b);
return
return 0;
0;
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
5/27
Integrierte Fehlerbehandlung
}}
public
public static
static void
void main(String[]
main(String[] args)
args) {{
int
int ret;
ret;
Excep2
Excep2 instance
instance == new
new Excep2();
Excep2();
if
if (( (( ret
ret == instance.doYourJob()
instance.doYourJob() )) << 00 ))
System.out.println("Fehlercode:
System.out.println("Fehlercode: "" ++ ret);
ret);
else
else
System.out.println("Job
System.out.println("Job done.");
done.");
}}
Konsole
java Excep2
a: 15
b: 0
Fehlercode: -1
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
6/27
Integrierte Fehlerbehandlung
●
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
●
Fehlerbehandlung integriert in "regulären" Code → schwer lesbar
●
●
Fehler sollten die Ausnahme sein → unnatürlich, den
Rückgabewert einer Funktion dem Fehlerfall zu widmen
Wenn eine Funktion tatsächlich einen Wert liefern soll, muss
entweder dieser Wert oder der Fehlercode innerhalb eines
Referenztypparameters zurückgegeben werden.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
7/27
Fehlercode als Referenzparameter
●
Beispiel: Angenommen, die Methode doYourJob druckt das Ergebnis
der Division a/b nicht aus, sondern liefert es als Ergebniswert zurück:
public
public class
class Excep3
Excep3 {{
public
public int
int doYourJob(int
doYourJob(int a,
a, int
int b,
b, int[]
int[] error)
error)
{{
}}
if
if (( bb ==
== 00 )) {{
error[0]
error[0] == -1;
-1;
return
return -1;
-1;
}}
error[0]
error[0] == 0;
0;
return
return a/b;
a/b;
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
8/27
Fehlercode als Referenzparameter
}}
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Scanner
Scanner scanner
scanner == new
new Scanner(System.in);
Scanner(System.in);
System.out.print("a:
");
System.out.print("a: ");
int
int aa == scanner.nextInt();
scanner.nextInt();
System.out.print("b:
System.out.print("b: ");
");
int
int bb == scanner.nextInt();
scanner.nextInt();
Excep3
Excep3 instance
instance == new
new Excep3();
Excep3();
int[]
error
=
new
int[1];
int[] error = new int[1];
int
int ret
ret == instance.doYourJob(a,
instance.doYourJob(a, b,
b, error);
error);
if
(
error[0]
==
-1
){
if ( error[0] == -1 ){
System.out.println("Fehlercode:
System.out.println("Fehlercode: "" ++ error[0]);
error[0]);
}}
else
else {{
System.out.println("a
System.out.println("a // bb == "" ++ ret);
ret);
System.out.println("Job
System.out.println("Job done.");
done.");
}}
}}
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
9/27
Fehlercode als Referenzparameter
●
●
●
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…
Moderne Programmiersprachen, wie z.B. C++ und Java,
verwenden Ausnahmen (exceptions) für die Fehlerbehandlung.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
10/27
Ausnahmen / Exceptions
●
●
●
●
Trennung von regulärem Code und Fehlerbehandlung.
Wenn eine Ausnahmesituation 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.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
11/27
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()
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
12/27
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.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
13/27
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 einem oder mehreren
catch-Blöcken.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
14/27
Abfangen von Exceptions
●
Beispiel:
public
public void
void doYourJob()
doYourJob() {{
Scanner
Scanner scanner
scanner == new
new Scanner(System.in);
Scanner(System.in);
System.out.print("a:
");
System.out.print("a: ");
int
int aa == scanner.nextInt();
scanner.nextInt();
System.out.print("b:
System.out.print("b: ");
");
int
int bb == scanner.nextInt();
scanner.nextInt();
}}
try
try {{
System.out.println("a/b
System.out.println("a/b == "" ++ a/b);
a/b);
}}
catch(ArithmeticException
catch(ArithmeticException e)
e) {{
System.out.println("Wir
System.out.println("Wir haben
haben da
da ein
ein Problem:
Problem: ""
++ e.getMessage());
e.getMessage());
System.out.println(
System.out.println(
"Das
"Das haetten
haetten Sie
Sie nicht
nicht tun
tun sollen...");
sollen...");
}}
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
15/27
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!
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
16/27
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
FileReader ff == new
new FileReader("vals.txt");
FileReader("vals.txt");
●
Beachte: Mit einem FileReader-Objekt kann man eine Datei nur
zeichenweise einlesen.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
17/27
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
BufferedReader bb == new
new BufferedReader(f);
BufferedReader(f);
●
Beide Anweisungen können zusammengefasst werden:
BufferedReader
BufferedReader bb ==
new
new BufferedReader(new
BufferedReader(new FileReader("vals.txt"));
FileReader("vals.txt"));
●
Damit sieht der 1. Lösungsversuch wie folgt aus:
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
18/27
Beispiel – Daten aus Datei lesen
import
import java.io.*;
java.io.*;
public
public class
class Mittelwert
Mittelwert {{
private
private static
static int
int anzahl
anzahl == 0;
0;
public
public static
static int
int parse(String
parse(String s)
s) {{
anzahl++;
anzahl++;
return
return Integer.parseInt(s);
Integer.parseInt(s);
}}
Fortsetzung auf nächster Folie
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
19/27
Beispiel – Daten aus Datei lesen
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Scanner
Scanner scanner
scanner == new
new Scanner(System.in);
Scanner(System.in);
System.out.print("Dateiname:
System.out.print("Dateiname: ");
");
String
String fileName
fileName == scanner.next();
scanner.next();
BufferedReader
BufferedReader datei
datei ==
new
new BufferedReader(new
BufferedReader(new FileReader(fileName));
FileReader(fileName));
double
double mittel
mittel == 0.0;
0.0;
String
String line
line == datei.readLine();
datei.readLine();
while
while (( line
line !=
!= null
null )) {{
mittel
mittel +=
+= parse(line);
parse(line);
line
line == datei.readLine();
datei.readLine();
}}
mittel
mittel /=
/= anzahl;
anzahl;
Fortsetzung
auf
nächster
Folie
System.out.println("Mittelwert:
System.out.println("Mittelwert: "" ++ mittel);
mittel);
}}
}}
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
20/27
Beispiel – Daten aus Datei lesen
Aber: Der Versuch, die Klasse zu übersetzen
(javac Mittelwert.java) liefert folgende Fehlermeldung:
Mittelwert.java:16:
Mittelwert.java:16:unreported
unreportedexception
exception
java.io.FileNotFoundException;
java.io.FileNotFoundException;must
mustbe
becaught
caughtor
or
declared
to
be
thrown
declared to be thrown
new
newBufferedReader(new
BufferedReader(newFileReader(fileName));
FileReader(fileName));
^^
Mittelwert.java:18:
Mittelwert.java:18:unreported
unreportedexception
exception
java.io.IOException;
must
be
caught
java.io.IOException; must be caughtor
ordeclared
declaredto
to
be
thrown
be thrown
String
Stringline
line==datei.readLine();
datei.readLine();
^^
Mittelwert.java:21:
Mittelwert.java:21:unreported
unreportedexception
exception
java.io.IOException;
must
be
caught
java.io.IOException; must be caughtor
ordeclared
declaredto
to
be
thrown
be thrown
line
line==datei.readLine();
datei.readLine();
^^
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
21/27
Beispiel – Daten aus Datei lesen
}}
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Scanner
Scanner scanner
scanner == new
new Scanner(System.in);
Scanner(System.in);
FileNotFoundException
System.out.print("Dateiname:
System.out.print("Dateiname: ");
");
möglich
String
String fileName
fileName == scanner.next();
scanner.next();
BufferedReader
BufferedReader datei
datei ==
new
new BufferedReader(new
BufferedReader(new FileReader(fileName));
FileReader(fileName));
double
double mittel
mittel == 0.0;
0.0;
String
String line
line == datei.readLine();
datei.readLine();
IOException
while
while (( line
line !=
!= null
null )) {{
möglich
mittel
+=
parse(line);
mittel += parse(line);
line
line == datei.readLine();
datei.readLine();
}}
mittel
mittel /=
/= anzahl;
anzahl;
System.out.println("Mittelwert:
System.out.println("Mittelwert: "" ++ mittel);
mittel);
}}
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
22/27
Beispiel – Daten aus Datei lesen
●
Mögliche Lösung: throws-Klausel im Kopf der main-Methode:
import
import java.io.*;
java.io.*;
import
import java.util.Scanner;
java.util.Scanner;
public
public class
class Mittelwert2
Mittelwert2 {{
private
private static
static int
int anzahl
anzahl == 0;
0;
public
static
int
parse(String
public static int parse(String s)
s) {{
……
}}
public
public static
static void
void main(String[]
main(String[] args)
args)
throws
FileNotFoundException,
throws FileNotFoundException, IOException
IOException {{
...
...
}}
}}
●
Effekt: Reicht die Exception durch zur aufrufenden Methode, in diesem Fall
das Java-Laufzeitsystem, das das Programm mit einer Fehlermeldung
abbricht.
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
23/27
Beispiel – Daten aus Datei lesen
Konsole
java
javaMittelwert2
Mittelwert2
Datei:
Datei:bals.txt
bals.txt
Exception
Exceptionin
inthread
thread"main"
"main"java.io.FileNotFoundException:
java.io.FileNotFoundException:bals.txt
bals.txt
(Das
(DasSystem
Systemkann
kanndie
dieangegebene
angegebeneDatei
Dateinicht
nichtfinden)
finden)
at
atjava.io.FileInputStream.open(Native
java.io.FileInputStream.open(NativeMethod)
Method)
at
atjava.io.FileInputStream.<init>(Unknown
java.io.FileInputStream.<init>(UnknownSource)
Source)
at
atjava.io.FileInputStream.<init>(Unknown
java.io.FileInputStream.<init>(UnknownSource)
Source)
at
atjava.io.FileReader.<init>(Unknown
java.io.FileReader.<init>(UnknownSource)
Source)
at
atMittelwert.main(Mittelwert2.java:16)
Mittelwert.main(Mittelwert2.java:16)
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
24/27
Beispiel – Daten aus Datei lesen
●
Alternative: Exceptions abfangen
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BufferedReader
BufferedReader datei
datei == null;
null;
Scanner
scanner
=
new
Scanner(System.in);
Scanner scanner = new Scanner(System.in);
boolean
boolean success;
success;
do
do {{
System.out.println("Dateiname:
System.out.println("Dateiname: ");
");
String
fileName
=
scanner.next("Dateiname:
String fileName = scanner.next("Dateiname: ");
");
System.out.println("Datei:
"
+
fileName);
System.out.println("Datei: " + fileName);
try
try {{
datei
datei ==
new
new BufferedReader(new
BufferedReader(new FileReader(fileName));
FileReader(fileName));
success
=
true;
success = true;
}}
catch
catch (( FileNotFoundException
FileNotFoundException ee )) {{
success
success == false;
false;
}}
}} while
while (( !success
!success );
);
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
25/27
Beispiel – Daten aus Datei lesen
double
double mittel
mittel == 0.0;
0.0;
}}
try
try {{
String
String line
line == datei.readLine();
datei.readLine();
while
(
line
!=
while ( line != null
null )) {{
mittel
mittel +=
+= parse(line);
parse(line);
line
line == datei.readLine();
datei.readLine();
}}
mittel
mittel /=
/= anzahl;
anzahl;
System.out.println("Mittelwert:
System.out.println("Mittelwert: "" ++ mittel);
mittel);
}}
catch
catch (( IOException
IOException ee )) {{
System.out.println("Fehler
System.out.println("Fehler beim
beim Einlesen");
Einlesen");
System.exit(0);
System.exit(0);
}}
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
26/27
Erzeugen von Exceptions
●
Mit der throw-Anweisung können Exceptions auch selbst ausgelöst
werden:
Syntaxregel
throw <Exception>
●
Beispiel:
if
if (param
(param <=
<= 0){
0){
Exception
Exception newException
newException == new
new IllegalArgumentException(
IllegalArgumentException(
"Parameter
muss
größer
Null
sein"
"Parameter muss größer Null sein");
);
throw
newException;
throw newException;
}}
Prof. Dr. Oliver Haase, HTWG Konstanz
Karl Martin Kern, Seitenbau GmbH
Achim Bitzer, Seitenbau GmbH
27/27
Herunterladen