Exceptions - KIT

Werbung
Programmieren I
Fehlerbehandlung – Exceptions

Heusch 2. Bd., 3
Ratz 10
Institut für Angewandte Informatik
KIT – Die Forschungsuniversität in der Helmholtz-Gemeinschaft
www.kit.edu
Exceptions und ihre Behandlung
Eine Exception ist eine Ausnahmesituation (wie z.B. Fehler)
Eine Exception erzeugen (werfen,
engl. „to throw“) bedeutet, eine
Ausnahmesituation zu
signalisieren.
Eine Exception abfangen (engl.
„to catch“) bedeutet, eine
Ausnahmesituation zu behandeln,
d.h. alle Aktionen durchzuführen,
die notwendig sind, um auf die
Situation angemessen zu
reagieren.
2
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Exception-Objekte
In einem Programm wird eine Ausnahmesituation, die
auftritt, durch ein Objekt repräsentiert,
und zwar durch eine Instanz einer Unterklasse der Klasse
java.lang.Throwable.
Throwable besitzt 2 Standardunterklassen:
java.lang.Error
für Probleme z.B. beim dynamischen Laden oder in der JVM. Sie
werden i.d.R. nicht abgefangen.
java.lang.Exception
für Ausnahmesituationen, die abgefangen und behoben werden
können, z.B.
Leseversuche über Dateiende hinaus (java.io.EOFException) oder
Überschreitungen der Array-Grenzen
(java.lang.ArrayIndexOutofBoundsException )
3
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Exception-Handling
Exceptions können mit Hilfe von try-catch-finallyAnweisungen behandelt werden. Bestandteile:
try-Block
Der try-Block ist das Codestück, das überwacht werden soll (d.h. von
dem Exceptions und abnormale Abbrüche behandelt werden sollen).
catch-Blöcke
Dem try-Block folgen null, ein oder mehrere catch-Blöcke,
diejeweils bestimmte Exception-Typen abfangen und behandeln.
finally-Block
Den catch-Blöcken kann ein finally-Block folgen, der die trycatch-finally-Anweisung abschließt.
Die Anweisungen im finally-Block werden immer ausgeführt,
gleichgültig mit welchem Status der try-Block beendet wird.
4
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Exception-Handling: So sieht der Code aus
try {
/* Programmcode, in dem eine Exceptions auftreten kann */
}
catch (ExceptionType1 e1) {
/* Code, der Exceptions vom Typ ExceptionType1 behandelt */
}
catch (ExceptionType2 e2) {
/* Code, der Exceptions vom Typ ExceptionType2 behandelt */
}
finally {
/* Code, der immer ausgeführt wird */
}
e1, e2: Referenzvariablen auf die Exception-Objekte
Man beachte: Innerhalb dieser Blöcke definierte Variablen sind
außerhalb des jeweiligen Blocks nicht sichtbar!
5
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Beispiel für Exception-Handling:
Konvertierung von String in ganze Zahl
import java.util.Scanner;
public class ExceptionExample {
public static void main(String[] args) {
try {
System.out.print("Please enter an integer: ");
Scanner scan = new Scanner(System.in);
String input = scan.next();
// String einlesen
int intNumber = Integer.parseInt(input); // Exception möglich
System.out.println("Tripled: " + 3 * intNumber);
} catch (NumberFormatException e) {
System.err.println("Error during conversion: " + e.getMessage());
e.printStackTrace();
}
}
}
6
Beispieldialog:
Please enter an integer: a
Error during conversion: For input string: "a"
...
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Einige Methoden der Klasse Throwable
String getMessage()
Liefert den Beschreibungs-String der Exception.
String toString()
Liefert eine Beschreibung der Exception.
void printStackTrace()
Gibt den Call-Stack-Trace (Aufruf-Hierarchie) aus.
Aufruf im Beispiel:
e.printStackTrace();
Ausgabe im Beispiel (bei Eingabe von „a“):
Ausgabe
Error during conversion: For input string: "a"
java.lang.NumberFormatException: For input string: "a"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at slides.exceptions.ExceptionExample.main(ExceptionExample.java:17)
7
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Call-Stack-Trace: Beispiel aus der Praxis
EJava.Exception.InvocationException:/uinbw/Entry/uinbw2GSA.html (Line: 36)
failed to invoke method 'nextPageURL' on object Application.gsa.Search@132021a with parameters:
[Ljava.lang.Object;@2803d5
at EJava.Reflection.JavaMethodInvocation.value(JavaMethodInvocation.java:141)
at EJava.Scripting.AccessStatement.doProcess(AccessStatement.java:52)
at EJava.Scripting.ScriptingElement.processWith(ScriptingElement.java:133)
at EJava.Interpreter.processAll(Interpreter.java:286)
at EJava.Interpreter.processFileHelper(Interpreter.java:266)
at EJava.Scripting.EmbedStatement.doProcess(EmbedStatement.java:75)
at EJava.Scripting.ScriptingElement.processWith(ScriptingElement.java:133)
at EJava.Interpreter.processAll(Interpreter.java:286)
at EJava.Scripting.ConditionalStatement.doProcess(ConditionalStatement.java:65)
at EJava.Scripting.ScriptingElement.processWith(ScriptingElement.java:133)
at EJava.Interpreter.processAll(Interpreter.java:286)
at EJava.Interpreter.processFileHelper(Interpreter.java:266)
at EJava.Scripting.EmbedStatement.doProcess(EmbedStatement.java:75)
at EJava.Scripting.ScriptingElement.processWith(ScriptingElement.java:133)
at EJava.Interpreter.processAll(Interpreter.java:286)
…
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:468)
at java.lang.Integer.parseInt(Integer.java:497)
at Application.gsa.Search.nextPageURL(Search.java:779)
at sun.reflect.GeneratedMethodAccessor50.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorIm.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at EJava.Reflection.JavaMethodInvocation.value(JavaMethodInvocation.java:131)
…
8
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Exceptions weiterleiten
Java erfordert, dass jede Methode, in der eine Exception auftreten
kann, diese Exception
entweder abfängt und behandelt (try-catch-finally-Anweisung)
oder an die aufrufende Methode "weiterwirft" (weiterleitet),
indem im Methodenkopf in einer throws-Klausel der Typ der
Exception angegeben wird.
Zwei Beispiele für das Letztere:
public void openFile(/*...*/) throws IOException {
/* Hier stehen Anweisungen, die eine nicht abgefangene
* java.io.IOException verursachen können. */
}
public
/*
*
*
}
9
void myFunc(/*...*/) throws TooBigEx, TooSmallEx, DivByZeroEx {
Hier stehen Anweisungen, die die nicht abgefangenen
Exceptions TooBigEx, TooSmallEx und DivByZeroEx
verursachen können. */
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Eigene Exceptions erzeugen
Bisher haben wir Standard-Exceptions von Java betrachtet.
Diese sind Objekte der Klasse Throwable oder deren Unterklassen
Error und Exception oder wiederum einer deren Unterklassen
(siehe java.oracle.com).
Zusätzlich zu diesen Klassen können auch eigene ExceptionKlassen deklariert werden und Exceptions ausgelöst werden.
Beispiel für die Deklaration einer eigenen Exception-Klasse:
class MyException extends Exception {
public MyException(){
}
public MyException(String message){
super(message);
}
}
10
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Eigene Exceptions: Weiteres Beispiel (1)
// Deklaration der Exception-Klasse DivZeroException
public class DivZeroException extends Exception {
public DivZeroException(){
}
public DivZeroException(String message){
super(message);
}
}
11
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Eigene Exceptions: Weiteres Beispiel (2)
// Erzeugen und werfen der Exception
public class MyMath {
public static int divide(int a, int b)
throws DivZeroException {
if ( b == 0 ){
// Exception-Objekt erzeugen und werfen der Exception
throw new DivZeroException("Division by zero!");
} else {
return a / b; // Ganzzahldivision
}
}
}
12
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Eigene Exceptions: Weiteres Beispiel (3)
public class Test {
public static void main(String[] args) {
int res;
// Abfangen und behandeln der Exception
try {
res = MyMath.divide(8, 0);
System.out.println("Result: " + res);
} catch (DivZeroException e) {
System.out.println(e.getMessage());
}
}
}
13
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Exception-Matching (1)
Nach einem try-Block können mehrere catch-Blöcke auftreten.
Der Exception-Handler sucht in den catch-Blöcken den ersten, der „passt“.
Dabei ist kein „genaues passen“ erforderlich.
Ein Exception-Objekt einer Unterklasse wird auch vom catch-Bock einer
Oberklasse gefangen. Beispiel:
class FatherException extends Exception { /*...*/ }
class SonException extends FatherException { /*...*/ }
public class FatherAndSon {
public static void main(String[] args) {
try { throw new SonException(); }
catch( SonException s ){
System.err.println("Caught SonException");
}
catch (FatherException f) {
System.err.println("Caught FatherException");
}
}
Ausgabe: Caught SonException
}
14
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Exception-Matching (2)
Die SonException wird hier vom ersten catch-Block gefangen.
Wenn der erste catch-Block gelöscht wird, so ist der Code immer
noch lauffähig, da catch (FatherException f)
alle FatherExceptions sowie von ihr abgeleiteten Exceptions fängt.
Das Vertauschen der catch-Blöcke zu
try {
throw new SonException();
}
catch (FatherException f) {
System.err.println("Caught FatherException");
}
catch( SonException s ){
System.err.println("Caught SonException");
}
führt zu einem Fehler beim Compilieren, da der Compiler erkennt, dass
der SonException-catch-Block nie erreicht werden kann.
15
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Runtime-Exceptions
Bei RuntimeExceptions handelt es sich um bestimmte
Laufzeitfehler, die an vielen Stellen im Programm auftreten
können, z.B.
Zugriff auf Arrays über die Arraygrenze hinaus
(ArrayIndexOutOfBoundsException)
Zugriff über eine leere Referenz (NullPointerException)
NumberFormatException
fehlerhafte Typkonvertierung (ClassCastException)
RuntimeExceptions müssen nicht abgefangen werden
(„unchecked exceptions“).
16
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Erweiterungen seit Java 1.7
In Java sind seit 1.7 mehrere Exception-Typen in einem
Catch-Block möglich (separiert durch "|")
try {
throwAorB();
}
catch( ExceptionA | ExceptionB ex ){
throw ex;
}
Das erneute Werfen einer Exception in einem catch-Block
(re-throw) erzeugt ein Objekt vom Typ der ursprünglich
geworfenen Exception, und nicht mehr vom Typ der
gefangenen Exception (die z.B. auch eine Oberklasse
davon sein kann).
Ab Java 1.7
17
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Kleine Übungsaufgabe zu Exceptions
Schreiben Sie im Package de.dhbwka.java.exercise.exceptions
eine Exception-Klasse MyParameterException für eine ParameterAusnahmesituation (unerlaubter Parameterwert).
Schreiben Sie im gleichen Package in einer Klasse MyMath eine eigene
Methode static double mySqrt(double zahl)
zur Berechnung der Quadratwurzel einer Zahl. Diese Methode soll für
zahl< 0 eine MyParameterException werfen. Für zahl ≥ 0 soll der
Rückgabewert gemäß dem Babylonischen-Wurzelziehen-Verfahren
bestimmt werden – siehe Aufgabe „Babylonisches Wurzelziehen“ im
Übungsblatt „Kontrollstrukturen“. (Zur Vereinfachung kann für zahl ≥ 0
der Rückgabewert auch mit Math.sqrt() bestimmt werden.)
Schreiben Sie außerdem eine Test-Methode, die eine reelle Zahl einliest,
mit dieser Zahl als Parameter die Methode mySqrt() aufruft, die
MyParameterException von mySqrt() behandelt und den ExceptionString bzw. den Rückgabewert der Methode ausgibt.
18
W. Geiger, W. Süß, T. Schlachter, C. Schmitt
Institut für Angewandte Informatik
Herunterladen