§ kein Speicher mehr! § Division durch Null (bei int) § Zugriff auf ein

Werbung
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
K25 EXCEPTIONS
1 Einführung
Während der Ausführung eines Programms können viele Arten
von Fehlern auftreten.
Ernste Fehler bzw. Errors erfordern eine sofortige Reaktion des
Programms. Beispiele sind:
§
kein Speicher mehr!
§
Division durch Null (bei int)
§
Zugriff auf ein nicht mehr vorhandenes
Objekt
§
Überschreiten von Arraygrenzen
Fehler bzw. abnormale Situationen können auch nachträglich
und "ohne Fehler" des Programms entstehen. Da solche Situationen hoffentlich nur selten auftreten, werden sie als Ausnahmen
bzw. Exceptions bezeichnet. Beispiele sind:
§
fehlende Datei auf Festplatte
§
Falscheingabe des Benutzers
§
Papierstau beim Drucker
§
Verlust einer Netzwerkverbindung
Man kennt also diverse Arten von Fehlern, die in der Regel verschieden sowie auf unterschiedlichen Stufen behandelt werden
müssen.
K25_Exceptions-L, V86
© H. Diethelm
Seite 1/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
2 Unbefriedigender Lösungsansatz
Grundsätzlich könnten Ausnahmen mit Hilfe der uns bereits bekannten Kontrollstrukturen behandelt werden. Folgendes Programmgerüst zeigt einen möglichen Ansatz:
public boolean doA() { .... }
public boolean doB() { .... }
public boolean doC() { .... }
public void doABC() {
boolean okA, okB, okC;
okA = doA();
if (!okA) {
handleProblemA();
} else {
okB = doB();
if (!okB) {
handleProblemB();
} else {
okC = doC();
if (!okC) {
handleProblemC();
}
}
}
}
Nachteile:
§
Die Ausnahmen dominieren die Programmlogik. Das Programm ist schwierig
lesbar und wartbar.
K25_Exceptions-L, V86
© H. Diethelm
Seite 2/15
FHZ
Hochschule für Technik+Architektur Luzern
Abteilung Informatik, Fach Programmieren
K25 EXCEPTIONS
§
Der Rückgabewert wird für die Ausnahmebehandlung "verschwendet". (Eine
mehrdeutige Interpretation ist zu vermeiden, z.B. "-1 für Fehler".)
3 Lösungsansatz von Java
Wie fast alle modernen Programmiersprachen unterstützt auch Java die Behandlung von Ausnahmen mit speziellen Sprachkonstrukten. Folgende Schlüsselwörter werden dafür verwendet:
§
try, catch, finally, throws, throw
Die Ausnahmebehandlung ist so realisiert, dass sich Normalfall
(vgl. try) und Ausnahmefall (vgl. catch) im Sourcecode separieren lassen.
Ein Objekt einer Exception-Klasse (oder Error-Klasse) signalisiert dabei eine aufgetretene Ausnahme. Das Objekt kann zudem
die Ausnahmebehandlung detaillierter über die aufgetretene
Ausnahme informieren.
3.1 Einführungsbeispiel 1
JDK-Dokumentation der Methode Integer.parseInt(...):
K25_Exceptions-L, V86
© H. Diethelm
Seite 3/15
FHZ
Hochschule für Technik+Architektur Luzern
Abteilung Informatik, Fach Programmieren
K25 EXCEPTIONS
Sourcecode:
import java.awt.*; import java.applet.Applet;
import java.awt.event.*;
public class ExceptionDemo1 extends Applet
implements ActionListener {
private TextField stringField, resultField;
private Label resultLabel, stringLabel;
public void init() {
stringLabel = new Label("Integer-Value? ");
resultLabel = new Label("Answer: ");
stringField = new TextField(20);
resultField = new TextField(20);
resultField.setEditable(false);
add(stringLabel); add(stringField);
stringField.addActionListener(this);
add(resultLabel); add(resultField);
}
public void actionPerformed(ActionEvent ev) {
if (ev.getSource() == stringField) {
try{
int number = Integer.
parseInt(stringField.getText());
resultField.setText("Doubled Value is "
+(2*number));
}
catch (NumberFormatException ex) {
resultField.setText("Error, retype!");
}
}
}
}
K25_Exceptions-L, V86
© H. Diethelm
Seite 4/15
FHZ
Hochschule für Technik+Architektur Luzern
Abteilung Informatik, Fach Programmieren
K25 EXCEPTIONS
Screen-Shots:
Veranschaulichung:
actionPerformed(...)
try-Block mit
o
Meth
ufruf
dena
parseInt(...)
parseInt(...)-Aufruf
Eine Ausnahmebedingung
wirft NumberFormatException
bzw. entsprechendes Objekt
catch-Block mit
NumberFormatExceptionHandler
no
M rm
rü etho aler
ck d
sp en
ru ng
Erklärungen:
§ Falls eine Ausnahme auftritt, geht die Kontrolle direkt zum
catch-Block über.
§ Die Klasse NumberFormatException bzw. entsprechende
Exceptions sind unchecked. Mit anderen Worten: Der Compiler
verlangt nicht zwingend, dass ein parseInt(...)-Aufruf,
welcher bekanntlich eine NumberFormatException auslösen
kann, von einem try-Block aus aufgerufen und diese Exception in einem catch-Block behandelt wird.
Es ginge also auch wie folgt:
K25_Exceptions-L, V86
© H. Diethelm
Seite 5/15
FHZ
Hochschule für Technik+Architektur Luzern
Abteilung Informatik, Fach Programmieren
K25 EXCEPTIONS
3.2 Einführungsbeispiel 2
Sourcecode:
import java.awt.*; import java.applet.Applet;
import java.awt.event.*;
public class ExceptionDemo2 extends Applet
implements ActionListener {
private TextField stringField, resultField;
private Label resultLabel, stringLabel;
public void init() {
stringLabel = new Label("Integer-Value? ");
resultLabel = new Label("Answer: ");
stringField = new TextField(20);
resultField = new TextField(20);
resultField.setEditable(false);
add(stringLabel); add(stringField);
stringField.addActionListener(this);
add(resultLabel); add(resultField);
}
public void actionPerformed(ActionEvent ev) {
if (ev.getSource() == stringField) {
int number = Integer.
parseInt(stringField.getText());
resultField.setText("Doubled Value is "
+(2*number));
}
}
}
K25_Exceptions-L, V86
© H. Diethelm
Seite 6/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
Screen-Shots:
Veranschaulichung:
method1(...)
method2(...)
parseInt(...)
actionPerformed(...)
od
Meth
e
uf
naufr
parseInt(...)-Aufruf
Eine Ausnahmebedingung
wirft NumberFormatException
bzw. entsprechendes Objekt
no
M rm
rü etho aler
ck d
s p en
ru ng
K25_Exceptions-L, V86
© H. Diethelm
Seite 7/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
Erklärungen:
§ Falls in der Methode actionPerformed(...) eine NumberFormatException nicht mit einem catch-Block abgefangen wird, wird die Exception an jene Methode weitergeleitet,
welche actionPerformed(...) aufgerufen hat usw. Die Exception wird so lange "nach oben weitergereicht", bis sie jemand behandelt. Im Extremfall ist dies das Laufzeitsystem (vgl.
Screen-Shot, Stack der JVM).
§ Im Gegensatz zur Klasse NumberFormatException ist z.B.
die Klasse FileNotFoundException checked. In diesem
Fall verlangt der Compiler zwingend, dass eine Methode, welche diese Exception auslösen kann, in einem try-Block aufgerufen und diese Exception im zugehörigen catch-Block an "Ort
und Stelle" behandelt wird! Alternativ ist möglich, dass man die
Exception explizit "nach oben weiterreicht". Dies geschieht
mit Hilfe des Schlüsselwortes throws.
Beide Varianten illustriert das nächste Beispiel:
K25_Exceptions-L, V86
© H. Diethelm
Seite 8/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
3.3 Einführungsbeispiel 3
JDK-Dokumentation des Konstruktors FileReader(...):
Sourcecode:
public void openFile1() {
try {
inFile = new BufferedReader(new
FileReader("myfile.txt"));
}
catch (FileNotFoundException ex) {
errorField.setText("missing File,
enter again!");
}
}
public void openFile2()
throws FileNotFoundException {
inFile = new BufferedReader(new
FileReader("myfile.txt"));
}
Erklärungen:
§ Die erste Variante dürfte die Bessere sein, weil sie die Ausnahme unmittelbar behandelt und den Benutzer zur nochmaligen Eingabe auffordert.
§ Die zweite Variante zeigt, wie man die Weitergabe der
Exception in der Signatur der Methode mit Hilfe von throws
angibt.
K25_Exceptions-L, V86
Seite 9/15
© H. Diethelm
FHZ
Hochschule für Technik+Architektur Luzern
Abteilung Informatik, Fach Programmieren
K25 EXCEPTIONS
4 Exception-Klassen
Alle Ausnahmen in Java sind als eigenständige Objekte der Klasse
java.lang.Throwable oder einer Unterklasse von Throwable
realisiert. Damit kann eine ganze Hierarchie von Ausnahmen
aufgebaut werden. Folgendes Klassendiagramm zeigt nur einen
kleinen Ausschnitt:
Object
equals():boolean
Throwable
getMessage():Str
ing
Error
LinkageError
Exception
all unchecked
VirtualMachine
Error
IOException
ClassNotFound
Exception
all checked, except for
RuntimeException
RuntimeExcepti
on
printStackTrace()
:void
OutOfMemoryEr
ror
StackOverflowE
rror
FileNotFoundEx
ception
ArithmeticExce
ption
IndexOutOfBou
ndsException
IllegalArgument
Exception
ArrayIndexOutO
fBoundsExcepti
on
NumberFormat
Exception
An der Wurzel dieser Hierarchie stehen die direkt von Throwable
abgeleiteten Klassen Error und Exception.
K25_Exceptions-L, V86
© H. Diethelm
Seite 10/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
Obwohl die genaue Trennung dieser beiden Klassen schwierig ist,
sind Error-Ausnahmen typisch auf Systemfehler zurückzuführen, die vom Java-Programm nicht korrigiert werden können, z.B.
"kein Speicher mehr". Solche Ausnahmen sind unchecked und
ein Programm wird in der Regel nicht versuchen, ErrorAusnahmen abzufangen und zu behandeln.
Die Ursachen von Ausnahmen der Klasse Exception und deren
Unterklassen sind dagegen meistens auf Probleme des Anwendungsprogrammes zurückzuführen und müssen daher abgefangen werden, z.B. fehlende Datei auf der Festplatte. Diese Ausnahmen sind deshalb checked. Der Compiler verlangt also, dass
Methodenaufrufe, die solche Ausnahmen auslösen können, in einem try-Block aufgerufen werden.
Aus der Reihe tanzen einzig die Klasse RunTimeException und
ihre Unterklassen, welche unchecked sind! Entsprechende Ausnahmen rühren typisch von Arithmetik- (vgl. Division durch Null)
und Array-Operationen (vgl. unzulässiger Index) her. Weil solche
Operationen sehr häufig vorkommen, ist es dem Programmierer
überlassen, wie weit er diese Ausnahmen (z.B. ArithmeticException, ArrayIndexOutOfBoundsException) selber abfangen will; das Laufzeitsystem wird es spätestens tun.
K25_Exceptions-L, V86
© H. Diethelm
Seite 11/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
5 Benutzerdefinierte Exceptions
Anwendung:
Benutzerdefinierte Exception-Klasse:
public class NoDigitException extends Exception
{
public NoDigitException(String s) {
super(s);
}
}
Benutzerdefinierte Methode, welche obige Exception wirft:
public class NumberNames {
private static String[] names =
{"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"};
public static int convertToNumber(String name)
throws NoDigitException {
for (int i=0; i<10; i++) {
if (names[i].equals(name)) return i;
}
throw new NoDigitException(name +
" is not a digit!");
}
}
K25_Exceptions-L, V86
© H. Diethelm
Seite 12/15
FHZ
Hochschule für Technik+Architektur Luzern
Abteilung Informatik, Fach Programmieren
K25 EXCEPTIONS
Applet, das von obiger Methode Gebrauch macht:
import java.applet.Applet;
import java.awt.*; import java.awt.event.*;
public class TestNumberNames extends Applet
implements ActionListener {
private TextField inputField; outputField;
public void init() {
Label label = new Label("Name of a number
(e.g. three)?"); add(label);
inputField = new TextField (5);
inputField.addActionListener(this);
add(inputField);
outputField = new TextField (20);
outputField.setEditable(false);
add(outputField);
}
public void paint (Graphics g) { }
public void actionPerformed(ActionEvent ev) {
try {
outputField.setText("The number is " +
NumberNames.convertToNumber
(inputField.getText()));
}
catch (NoDigitException ex) {
outputField.setText("Exception: " +
ex.getMessage());
}
}
}
K25_Exceptions-L, V86
© H. Diethelm
Seite 13/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
6 Exception-Hierachie und finally
Beispiel:
import java.net.*;
...
try {
// Versuch, eine Datei von einem WWW-Server
// über eine URL zu laden:
URL aURL = new
URL("http://www.hta.fhz.ch/index.html");
...
}
catch (MalformedURLException ex1) {
// Schreibweise der URL (Protokoll/Adresse)
// falsch
...
}
catch (UnknownHostException ex2) {
// Server kann nicht ermittelt werden
...
}
catch (IOException ex3) {
// Übertragung der Datei misslungen
...
catch (Exception ex4) {
// allgemeiner Fehler
...
}
finally {
// in jedem Fall geöffnete Netzwerk// verbindung schliessen
...
}
...
K25_Exceptions-L, V86
© H. Diethelm
Seite 14/15
Abteilung Informatik, Fach Programmieren
FHZ
Hochschule für Technik+Architektur Luzern
K25 EXCEPTIONS
Bemerkungen:
§ Es besteht die Möglichkeit, mit Hilfe von mehreren catchBlöcken sehr flexibel und differenziert auf verschiedene
Ausnahmen zu reagieren.
§ Die Anordnung der einzelnen catch-Blöcke ist relevant,
weil die Blöcke von oben nach unten durchsucht werden, um eine Ausnahme abzufangen. Deshalb müssen die catch-Blöcke
für Exception-Unterklassen immer vor ihren Oberklassen
stehen, da sie sonst gar nicht erreichbar wären (vgl. speziellere
vs. allgemeinere Ausnahmen)! Der Compiler reklamiert, falls
diese Regel nicht eingehalten wird.
§ Der finally-Block ist optional. Er wird in jedem Fall ausgeführt, entweder im Anschluss an den try- oder einen catchBlock. Er wird selbst dann ausgeführt, wenn im try- oder einem
catch-Block mit einer return-Anweisung die Methode verlassen wird! Im finally-Block lassen sich typisch "Aufräumarbeiten" durchführen.
§ Auf einen try-Block muss mindestens ein catch- oder
finally-Block folgen.
K25_Exceptions-L, V86
© H. Diethelm
Seite 15/15
Herunterladen