Exception (Java)

Aus Byte-Welt Wiki
Wechseln zu: Navigation, Suche
Dieser Artikel überschneidet sich inhaltlich teilweise mit Was ist eine Exception?

Da es neben den Syntaxfehlern auch Fehler gibt die zur Laufzeit eines Programms auftreten können, wird in Java das Prinzip der Exceptions verwendet. Dabei gibt es für die Fehler eine extra Einteilung, als oberste Klasse ist die Klasse Throwable, von ihr gibt es zwei abgeleitete Klassen.

Error

Die Fehler der Error-Klasse werden nur bei schweren Ausnahmen ausgelöst, so z.B. wenn eine Klasse oder Methoden/Attribute einer Klasse nicht gefunden wurde. Auch wenn die meisten Fälle in denen ein Error auftreten kann durch den Compiler vorher überprüft werden können ist es nicht sichergestellt das diese nie eintreten. So kann z.B. beim Schreiben der Klasse X die Klassen Y und Z vorhanden sein und der Compiler meldet keinen Fehler, jedoch kann später wenn man das Programm auf einem anderen System ausführt die Klasse Z nicht vorhanden sein und in diesem Fall wird der NoClassDefFoundError ausgelöst. In einem anderen Fall kann es vorkommen das eine Klasse X die Funktionen m1, m2 und m3 hat, in einer späteren Version wird die Methode m1 entfernt oder die Parameter ändern sich, startet man jetzt ein altes Programm was noch für die Klasse X die Methode m1 kennt (oder mit anderen Parametern kennt) aber die vorliegende Klasse ist schon die neue Klasse X kommt es zu dem NoSuchMethodError da die Methode für Java nicht vorhanden ist. Dies sind Fehler die der Compiler nicht beachten kann, da es für ihn nicht möglich ist sicher zustellen ob später alle Klassen an der richtigen Stelle liegen.

Andere Probleme können auf auftreten wenn der Speicher ausgeht, so z.B. der StackOverflowError dieser tritt immer ein wenn der Stack der VM zu voll ist, was zB. durch zu viele rekursive Schritte auftreten kann.

Exception

Die meisten Fehler die wären des Betriebs auftreten, sind von der Exception-Klasse, bzw. einer der abgeleiteten Klassen. Eine dieser abgeleiteten Klassen hat eine Besonderheit: bei der Klasse RuntimeException ist man nicht gezwungen die erzeugten Fehler durch einen try-catch Block abzufangen oder weiterzuleiten, wie bei den anderen Klassen. RuntimeExceptions werden oftmals ausgelöst wenn kleinere Fehlsituationen eintreten, so z.B. die NumberformatException, welche bei der Zahlenkonvertierung auftreten kann .

Fehlerbehandlung

Der Ablauf beim Auftreten eines Fehler läuft immer nach dem selben Schema ab, dazu sieht die VM in dem darüberliegenden Block nach ob hier eine Fehlerbehandlung vorhanden ist, ansonsten wird in den Block darüber gegangen. Ein Block kann ein Klammerpaar sein {}, Schleife, bedingte Anweisungen oder Methoden.

Damit ein Programm bei dem Auftritt eines Fehlers nicht abstürtzt muss dieser behandelt werden, dies geschieht in Java auf zwei mögliche Arten.

try-catch

Mit dem try-catch Block lassen sich alle Fehler, die bis zu einer bestimmten Fehlerklasse auftreten abfangen. Dabei werden nur Fehler inherhalb des try-Blocks abgefangen. Tritt ein Fehler auf wird dieser mit allen in den catch Anweisungen vorhandenen Exceptions verglichen. Wenn es sich in einem catch-Block um die gleiche Exception oder eine Oberklasse der aufgetretenen Exception handelt, wird die Anweisung die dem catch-Block folgt ausgeführt. Daraus resultiert das man bei einem try-Block mehrere catch-Blöcke schreiben kann, diese müssen jedoch nach unten immer allgemeiner werden, z.B.

try
{
  ...
  //Fehler tritt auf
  ...
}
catch(FileNotFoundException ex)
{
  System.out.println("Datei nicht gefunden");
}
catch(IOException ex)
{
  System.out.println("IO Fehler");
}
catch(Exception ex)
{
  System.out.println("Fehler");
}
catch(Error er)
{
  System.out.println("Error");
}
catch(Throwable t)
{
  System.out.println("Throw");
}

throws-Weiterleiten

Will man einen Fehler nicht behandeln sondern an die darüberliegende Schicht weiterreichen kann man den oder die Exception mit throws weiterleiten.

public void machwas() throws FileNotFoundExceptin, IOException, Exception
{
 ....
}


Ob man eine Exception weiter leitet oder verarbeitet hängt immer von der Anwendung ab. Da man Exceptions niemals verstecken sollte, sollte man sie da verarbeiten wo man dem Benutzer das auch mitteilen kann.

Um Missverständissen vorzubeugen, können höhere Ebenen Exceptions aus unteren Ebenen auffangen und an ihrer Stelle Exceptions werfen, die im Rahmen der höheren Abstraktion verständlich sind. Wenn z.B. in der Methode "get(int index)" eine Methode einer anderer Klasse aufgerufen wird, welche eine NoSuchElementException wirft, dann sollte sie diese auffangen und eine IndexOutOfBoundsException werfen, denn mit "NoSuchElement" weiss der Aufrufer von "get(int index)" nichts anzufangen. Diese Vorgehensweise nennt man Exception Translation:

public Object get(int index) {
    ListIterator i = listIterator(index);
    try {
        return i.next();
    } catch(NoSuchElementException e) {
        throw new IndexOutOfBoundsException("Index: " + index);
    }
}

Jedoch gibt es Fälle wo man keine Fehler weiterleiten kann. So unter anderem bei Schnittstellen oder Methoden, die man überschreibt. So z.B. muss man Exceptions bei dem Überschreiben der public void run() verarbeiten und kann sie nicht weiterleiten da dies die Signatur der Methode ändert.

Weblinks