In throw-Statements dürfen nur Objekte der Klasse
Throwable geworfen werden, insbesondere also keine
einfachen Typen. Die beiden Klassen Exception und
Error, JAVA-Klasse Error sind
Unterklassen von Throwable.
Man hat es aber fast immer nur mit Exception-Objekten zu tun, da sich
Errors meist auf Compiler- und Interpreter-Interna beziehen und
üblicherweise nicht abgefangen zu werden brauchen.
Eine Vielzahl von speziellen Ausnahmen wird von Exception abgeleitet,
und eigene Exceptions sollten natürlich auch immer Unterklasse dieser
Klasse sein.
Objekte, die geworfen werden sollen, werden in JAVA meistens mit
einem new im throw-Statement erzeugt:
- try
{
throw new Exception("Martians have landed.");
}
catch (Exception e)
{
System.out.println(e);
}
Hier wird der (String)-Konstruktor von
Exception verwendet (der natürlich von allen Unterklassen geerbt
wird).
Die Methode toString()
gibt den Namen der (Unter-)Klasse und diesen Text aus. Unterklassen
dürfen natürlich toString()-Methoden
definieren, die genauere Angaben machen. IndexOutOfBoundsException
baut zum Beispiel zusätzlich den schuldigen Index in den Text ein.
Beispielsweise entwerfen wir eine Exception, die ausgelöst wird,
wenn in einer Scanner-Routine für irgendeine Eingabe ein ungültiges
Zeichen gelesen wird:
- class IllegalCharacterException extends Exception
{
char c;
public IllegalCharacterException(char thechar) { c=thechar; }
public String toString()
{
return "Illegal character '"+c+"' (code "+(int)c+") encountered.";
}
}
throw-Deklarationen werden strenger gehandhabt als in
C++. Checked exceptions müssen vom Programmierer
gehandhabt werden. Jede Methode muß in einer
throws-Klausel (Achtung:
umbenannt gegenüber C++) angeben, welche (checked) Exceptions sie
möglicherweise nicht abfängt und also nach außen weitergibt.
Wenn eine Methode aufgerufen wird, die angibt, eine bestimmte Exception
weiterzugeben, dann muß die aufrufende Routine entweder diese
Exception abfangen oder selbst in einem throws deklarieren:
- void mymethod() throws FileNotFoundException
{
FileReader fr=new FileReader("myfile.txt");
// ...
}
Da der Konstruktor von java.io.FileReader die
Exception FileNotFoundException wirft und diese innerhalb der Routine
nicht abgefangen wird, muß sie nach dem Funktionskopf angegeben werden.
(Mehrere Exceptions werden dort mit Kommas voneinander getrennt.)
Unchecked Exceptions sind im wesentlichen in der Unterklasse
RuntimeException zusammengefaßt. Sie brauchen also nicht
abgefangen oder deklariert zu werden. Sie werden an das Laufzeitsystem
weitergegeben und führen zu einem Fehlerabbruch des Programms.
Durch den Zwang zu throws-Deklarationen kann es der Compiler
erkennen, wenn eine bestimmte Exception in einem try-Block nicht
geworfen werden kann. Wird dennoch ein entsprechendes
catch-Statement angegeben, gibt er einen Fehler aus.