Ausnahmen ( Exceptions) bieten die Möglichkeit, Fehlersituationen zu behandeln, ohne den Code unleserlich zu machen.
Java bietet zwei Arten von Ausnahmen:
Eine Ausnahme wird
bei unerwarteten Umständen
ausgelöst ( throw).
Sie wird abgefangen ( catch) von
einem dafür zuständigen Konstrukt (weiter vorne in der Methodenaufrufkette).
Falls ein solches nicht existiert, übernimmt
ein Default Exception Handler.
Das Attributed-Interface
(Seite )
erweitern wir um eine Methode replaceValue(name, newval).
Wenn ein Attribut mit Namen name nicht existiert, soll eine Ausnahme NoSuchAttrException ausgelöst werden:
public class NoSuchAttrException extends Exception { public String attrName; public String newVal; NoSuchAttrException(String name, Object val) { super("No such attribute " + name); attrName = name; newVal = val; } }
Die Ausnahme NoSuchAttrException ist Problem-spezifisch und
besser geeignet, die Fehlersituation zu beschreiben als
allgemeine Ausnahmetypen.
Exceptions werden durch die throw-Anweisung ausgelöst, die die Programmausführung sofort abbricht.
Für unsere Erweiterung des Attributed-Interfaces in der neuen Methode
public void replaceValue(String name, Object newval) throws NoSuchAttrException { Attr attr = find(name); if (attr == null) throw new NoSuchAttrException (name, newval); attr.valueOf(newValue); }
Die throws-Klausel gibt an, welche Exceptions von einer Methode ausgelöst werden können:
type method(parameters) throws excpt1, excpt2, excpt2 ...
Alle Exception-Objekte aus Unterklassen von excpt1, excpt2 und excpt3 können von method ausgelöst werden.
Man könnte auch eine gemeinsame Oberklasse von
excpt1, excpt2
und excpt3 verwenden, verschleiert damit aber möglicherweise
nützliche Information.
Die ungeprüften Ausnahmen
werden nicht in der throws-Klausel angegeben.
Sie können im Prinzip von jeder Methode ausgelöst werden.
throws-Klauseln dafür würden
den Code unleserlich machen.
Ausnahmen werden abgefangen, indem man Programmcode in try-Klauseln einschließt.
try block catch (exception_type id) block catch (exception_type id) block ... finally block
Ausführung
Die Regeln sind eigentlich etwas komplizierter, da die catch-
und
finally-Blöcke ihrerseits Ausnahmen auslösen können.
Unser Beispiel:
try { attributedObj.replaceValue("Alter", 32); } catch (NoSuchAttrException e) // kann nicht vorkommen. // falls es doch vorkommt, // korrigieren wir es: { Attr a = new Attr(e.attrName, e.newVal); attributedObj.add(a); }
finally ist bisweilen auch ohne Ausnahmebehandlung nützlich:
try { input = new Stream(file); while (!input.eof()) if (input.next() == word) return true; return false; // nicht gefunden } finally { if (input != null) input.close(); }
Der finally-Block wird immer mit einem bestimmten Grund
betreten:
Wird finally normal verlassen, bleibt dieser Grund für das
gesamte try bestehen.
Wird finally wegen Exception oder return verlassen, bestimmt dies den ``Grund'' der gesamten try-Anweisung.
Beispiel:
try { .... return 1; } finally { return 2; }
Gibt 2 zurück. Das wäre sogar so, wenn der try-Block
eine Ausnahme ausgelöst hätte.
Noch ein Beispiel:
class TestExcpt extends Exception { TestExcpt() {} TestExcpt(String s) {super(s);} } public class Test { public static void main(String[] a) { for (int i=0; i < a.length; i++) try { werfer(Integer.parseInt(a[i])); System.out.println("no exception"); } catch (Exception e) { System.out.println (e.getClass() + "\n\t" + e.getMessage()); } } static int werfer(int i) throws TestExcpt { switch (i) { case 0: return i/i; case 1: return (new int[-9]).length; case 2: throw new TestExcpt("Test"); } return 0; } }
Dieses Beispiel erzeugt beim Aufruf
java Test 0 1 2 3
die Ausgabe
class java.lang.ArithmeticException / by zero class java.lang.NegativeArraySizeException null class TestExcpt Test no exception