Die Verwendung und Behandlung von Exceptions wird teilweise sehr kontrovers diskutiert. Das dürfte daran liegen, dass man aufgrund der Vielzahl unterschiedlicher Software-Aufgabenstellungen nur sehr bedingt allgemein gültige Regeln dazu aufstellen kann und des Weiteren jeder seinen eigenen Programmierstil bezüglich des Umgangs mit Ausnahmebedingungen pflegt.
Exceptions sind, wie der Name schon sagt, Ausnahmen und sollten auf keinen Fall dazu verwendet werden, den normalen Programmfluss wie im folgenden Beispiel zu steuern:
public class ExceptionExample1
{ public static void main(String[] args)
{ String[] sArray = { "a", "b", "c" };
try // missbräuchliche Verwendung eine Exception
{ int i = 0;
while (true) System.out.println(sArray[i++]);
}
catch (Exception ex)
{ System.out.println ("Loop Ende");
}
}
}
C:\temp>java ExceptionExample1 a b c Loop Ende
Anders sieht es beispielsweise aus, wenn die Schnittstellenvereinbarung definiert, dass nur die Werte "a", "b" oder "c" übergeben werden dürfen, und es wird der Wert "d" übergeben. In diesem Fall handelt es sich um eine echte Abweichung von der Norm, die die Verwendung einer Exception rechtfertigt.
Ausnahmen fallen aus dem normalen Programmablauf heraus und fordern, soweit sie nicht von der Programmlogik zu korrigieren sind, eine Reaktion, die außerhalb der Zuständigkeit der entsprechenden Software liegt. Sie sind also in der Regel dazu gedacht, den Anwender mit sinnvollen Informationen zu versorgen, damit er durch geeignete Maßnahmen seine Arbeit nach Behebung der zugrunde liegenden Ursache fortsetzen kann. Anwender einer Software ist derjenige, der das Programm gestartet hat (Sachbearbeiter / Administrator) und ggf. der Betriebsverantwortliche.
Handelt es sich bei der Software um eine API, ist der Anwender der Softwareentwickler, der diese API nutzt und der entweder bei Auftreten einer Ausnahme seine Schnittstellenmethoden modifiziert oder aber entsprechende Ausnahme-Informationen aufbereitet an den End-User seiner Anwendung weiter gibt.
Bei der Entwicklung umfangreicherer Softwareprojekte habe ich selbst die Erfahrung gemacht, dass es am sinnvollsten ist, Ausnahmen, die nicht unmittelbar von der Software selbst behoben werden können, erst mal weiter ganz nach oben zu werfen. Oben bedeutet eine zentrale Ausgaberoutine, die in einer Batchanwendung den Fehler in Logfiles protokolliert und bei einer Dialoganwendung einen Fehlerdialog öffnet. Im Lauf der Fertigstellung der Software finden sich dann die Programmabschnitte,
SocketException
eine Exception mit dem Hinweis, dass das
Netzwerk oder der Proxy nicht erreichbar sind, zu generieren,
Nicht empfehlenswert ist meines Erachtens, wenn jede Methode auf dem Ausnahme-Stack ihren eigenen "Senf" dazu gibt oder eigene Exceptions mit eigener Interpretation generiert, da in diesem Fall das Programm mehr mit Ausnahmen als mit der Regel beschäftigt ist und äußerst unübersichtlich wird.
Java unterscheidet zwischen zwei Arten von Ausnahmen:
java.lang.RuntimeException
ableiten und
die nicht explizit mit einem try {} catch {}
Block zu behandeln sind, und
java.lang.Exception
abgeleiteten Exceptions, die explizit
entweder durch einentry {} catch {}
Block zu behandeln sind oder aber deren
potentiell betroffene Methode eine entsprechende throws
Klausel enthält.
Als grobe Faustregel, wann welche Exceptions zu verwenden sind, sollten unchecked Exceptions verwendet werden, wenn in Folge eines Programmfehlers keine sinnvolle Behandlung möglich ist und checked Exceptions für alle anderen Ausnahmen. Bedenken sollte man dabei allerdings, dass checked Exceptions wegen ihres Overheads nur sehr sparsam eingesetzt werden sollten.
Auch sollte man nicht für jedes neue Problem eigene Exceptions implementieren, sondern auf bereits im Java Sprachumfang vorhandene Klassen zurückgreifen wie beispielsweise:
java.lang.IllegalArgumentException
java.lang.IllegalStateException
Jede Exception sollte mit einem aussagekräftig beschriebenen Nachrichtentext versehen werden.
Das ist leider nicht immer der Fall und man sollte sich deshalb auch nicht darauf verlassen. So
wird vom Java Laufzeitsystem gern mal eine NullPointerException
geworfen,
deren Message NULL ist und wenn man diese dann nicht richtig auswertet bekomm man - was wohl? -
eine NullPointerException
und dann ist "Schicht im Schacht"!
Folgendes Beispiel demonstriert, wie man an welche Informationen einer Exception herankommen kann:
public class ExceptionExample2 { public static void main(String[] args) { int x = 0, y = 1; try { System.out.println(y / x); } catch (Exception ex) { System.out.println("Error: " + ex.getMessage()); StackTraceElement stackElements[] = ex.getStackTrace(); // stack[0] enthält die Methode, die die Exception geworfen hat. for (int i = 0; i < stackElements.length; i++) { System.out.println("Stack[" + i + "]"); String filename = stackElements[i].getFileName(); if (filename != null) { System.out.println(" Filename : " + filename); } System.out.println(" Classname : " + stackElements[i].getClassName()); System.out.println(" MethodName : " + stackElements[i].getMethodName()); System.out.println(" NativeMethod: " + stackElements[i].isNativeMethod()); System.out.println(" Line-Number : " + stackElements[i].getLineNumber()); } } } }
C:\temp>java ExceptionExample2 Error: / by zero Stack[0] Filename : ExceptionExample2.java Classname : ExceptionExample2 MethodName : main NativeMethod: false Line-Number : 5
Copyright © 2003 Wöhrmann Softwareentwicklung - Höhenkirchen-Siegertsbrunn - Landkreis München