1. Klasse Throwable: die Wurzel aller Ausnahmen
Jetzt betrachten wir ausführlich, wie das Ausnahmesystem in Java aufgebaut ist: Was ist Throwable, worin unterscheiden sich Exception und Error, und was bedeuten „geprüft“ und „ungeprüft“. Das ist das Fundament für eine saubere Fehlerbehandlung in Ihren Programmen.
In Java sind alle Ausnahmen und Fehler Objekte, die von der Klasse java.lang.Throwable erben.
Throwable ist der „Urahn“ der gesamten Hierarchie der Problembehandlung in Java.
Schematisch:
Throwable
├── Exception
└── Error
Throwable ist die Basisklasse für alles, was in Java „geworfen“ (throw) und „gefangen“ (catch) werden kann. Sie wird nicht direkt verwendet – sie dient als Grundlage für konkretere Fehlertypen.
Exception – für „normale“ Fehler
Exception ist die Basisklasse für alle Ausnahmen, die im Programm auftreten können und die man behandeln sollte. Das sind „Arbeitsfehler“: Probleme mit Dateien, Netzwerk, Ein-/Ausgabe, Benutzerfehler usw. Die meisten Ihrer try-catch-Blöcke arbeiten mit Unterklassen von Exception.
Beispiele:
- IOException – Fehler bei Datei- oder Netzwerkarbeit.
- SQLException – Fehler bei der Arbeit mit der Datenbank.
- FileNotFoundException – Datei nicht gefunden.
Error – für fatale JVM-Fehler
Error ist die Basisklasse für Fehler, die auf Ebene der Java Virtual Machine (JVM) auftreten. Das sind in der Regel kritische Ausfälle, die ein Programm nicht behandeln kann und auch nicht sollte. Wenn ein Error auftritt, kann die Anwendung in der Regel nicht fortfahren.
Beispiele:
- OutOfMemoryError – kein Speicher mehr.
- StackOverflowError – Stacküberlauf (z. B. durch unendliche Rekursion).
- NoClassDefFoundError – erforderliche Klasse nicht gefunden.
Wichtig:
Das Abfangen und Behandeln von Error ist fast immer eine schlechte Idee. Das sind keine Fehler Ihres Programms, sondern Ausfälle der Laufzeitumgebung.
2. Checked vs Unchecked Exceptions: Was bedeutet das?
In Java werden alle Ausnahmen in zwei große Gruppen eingeteilt:
Geprüfte (Checked) Ausnahmen
Was ist das? Ausnahmen, deren Behandlung oder explizite Weitergabe der Compiler erzwingt.
Wann treten sie auf? In der Regel im Zusammenhang mit externen Ressourcen: Dateien, Netzwerk, Datenbanken, Benutzereingaben.
Wie behandelt man sie? Entweder den Code in try-catch kapseln oder throws zur Methodensignatur hinzufügen.
Beispiele: IOException, SQLException, FileNotFoundException
Beispiel:
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path); // kann IOException auslösen
// ...
}
Wenn man sie weder behandelt noch weiterreicht – das Programm kompiliert nicht!
Ungeprüfte (Unchecked) Ausnahmen
Was ist das? Ausnahmen, die keine verpflichtende Behandlung durch den Compiler erfordern.
Wann treten sie auf? Meist Logikfehler: Division durch Null, Index außerhalb des Arrays, Zugriff auf null.
Wie behandelt man sie? Man kann sie abfangen, muss aber nicht. Besser ist es, solche Fehler durch Prüfungen zu verhindern.
Wo in der Hierarchie? Alle leiten sich von RuntimeException ab.
Beispiele: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, ArithmeticException
Beispiel:
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
Der Compiler zwingt Sie nicht, diese Ausnahme abzufangen – aber das Programm stürzt im Fehlerfall ab.
3. Die gesamte Hierarchie auf einen Blick
graph TD
Throwable --> Error
Throwable --> Exception
Exception --> RuntimeException
Exception --> CheckedExceptions["(andere Checked Exceptions)"]
Error --> OutOfMemoryError
Error --> StackOverflowError
RuntimeException --> NullPointerException
RuntimeException --> IndexOutOfBoundsException
RuntimeException --> IllegalArgumentException
%% Stile
style Throwable fill:#ffa64d,color:#000
style Exception fill:#ffa64d,color:#000
style CheckedExceptions fill:#ffa64d,color:#000
style Error fill:#ff4d4d,color:#fff
style OutOfMemoryError fill:#ff4d4d,color:#fff
style StackOverflowError fill:#ff4d4d,color:#fff
style RuntimeException fill:#4dff88,color:#000
style NullPointerException fill:#4dff88,color:#000
style IndexOutOfBoundsException fill:#4dff88,color:#000
style IllegalArgumentException fill:#4dff88,color:#000
Tabelle: die wichtigsten Unterschiede
| Gruppe | Oberklasse | Erfordert Behandlung? | Beispiele |
|---|---|---|---|
| Checked Exception | |
Ja | |
| Unchecked | |
Nein | |
| Error | |
Nein | |
4. Wie sieht das im Code aus?
Checked Exception: Beispiel mit Dateien
import java.io.*;
public class FileDemo {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
int data = reader.read();
System.out.println(data);
reader.close();
} catch (IOException e) {
System.out.println("Fehler bei der Dateiverarbeitung: " + e.getMessage());
}
}
}
Der Compiler erzwingt die Behandlung von IOException!
Unchecked Exception: Beispiel mit Division durch Null
public class ExceptionDemo {
public static void main(String[] args) {
int a = 10;
int b = 0;
int c = a / b; // ArithmeticException (unchecked)
System.out.println("Ergebnis: " + c);
}
}
Der Compiler verlangt keine Behandlung, aber das Programm wird abstürzen.
5. Warum braucht man eine Ausnahmehierarchie?
- Flexible Behandlung: Man kann sowohl konkrete Fehler (FileNotFoundException) als auch ganze Gruppen (IOException oder Exception) abfangen.
- Wiederverwendung von Code: Fehler eines Typs lassen sich zentral behandeln.
- Sauberer Code: Die Hauptlogik wird nicht mit Prüfungen für jedes Detail überfrachtet.
Beispiel:
try {
// gefährlicher Code
} catch (FileNotFoundException e) {
System.out.println("Datei nicht gefunden!");
} catch (IOException e) {
System.out.println("E/A-Fehler!");
} catch (Exception e) {
System.out.println("Etwas ist schiefgelaufen: " + e.getMessage());
}
6. Typische Fehler im Umgang mit Ausnahmen
Fehler Nr. 1: Ausnahmen ignorieren. catch (Exception e) {} zu schreiben – schlecht! Sie verlieren Informationen über die Fehlerursache.
Fehler Nr. 2: Zu viel abfangen. catch (Exception e) fängt alles ab, auch Unerwartetes. Besser nur die Ausnahmen abfangen, die Sie sinnvoll behandeln können.
Fehler Nr. 3: Errors abfangen (Error). Fangen Sie Error nicht ab, sofern Sie keinen Low-Level-Code schreiben. Das sind Probleme der JVM, nicht Ihres Programms.
Fehler Nr. 4: Checked und Unchecked nicht unterscheiden. Nicht alle Ausnahmen sind gleich! Checked erfordern Behandlung (Exception), Unchecked nicht (RuntimeException und deren Unterklassen).
Fehler Nr. 5: Ausnahmen ohne Kontext. Wenn Sie eigene Ausnahmen erstellen, fügen Sie immer eine aussagekräftige Meldung hinzu.
GO TO FULL VERSION