Exceptions verstehen
Exceptions in Java: Was sind Fehler, die Exception-Hierarchie, Checked vs. Unchecked Exceptions und wann du welche verwendest.
Exceptions verstehen
Fehler passieren — immer. Ein Benutzer gibt einen Buchstaben statt einer Zahl ein, eine Datei existiert nicht, oder das Netzwerk faellt aus. In Java werden solche Fehler durch Exceptions (Ausnahmen) dargestellt. In diesem Kapitel lernst du, was Exceptions sind und wie Javas Fehlersystem funktioniert.
Was sind Exceptions?
Eine Exception ist ein Objekt, das einen Fehler repraesentiert. Wenn ein Fehler auftritt, wird eine Exception geworfen (thrown). Wenn sie nicht gefangen (caught) wird, stuerzt das Programm ab:
public class ExceptionDemo {
public static void main(String[] args) {
int[] zahlen = {1, 2, 3};
System.out.println(zahlen[5]); // ArrayIndexOutOfBoundsException!
}
}
Ausgabe:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3
at ExceptionDemo.main(ExceptionDemo.java:4)
Die Fehlermeldung sagt dir:
- Welche Exception:
ArrayIndexOutOfBoundsException - Was passiert ist:
Index 5 out of bounds for length 3 - Wo:
ExceptionDemo.java:4(Datei, Zeile 4)
Die Exception-Hierarchie
Throwable
├── Error (schwere Fehler -- nicht fangen!)
│ ├── OutOfMemoryError
│ ├── StackOverflowError
│ └── ...
└── Exception
├── RuntimeException (Unchecked -- optionales Fangen)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ ├── IllegalArgumentException
│ ├── NumberFormatException
│ ├── ClassCastException
│ └── ArithmeticException
└── Checked Exceptions (Fangen ist PFLICHT)
├── IOException
├── FileNotFoundException
├── SQLException
└── ...
Checked vs. Unchecked Exceptions
Das ist einer der wichtigsten Unterschiede in Java:
Unchecked Exceptions (RuntimeException)
- Nicht obligatorisch zu fangen
- Entstehen durch Programmierfehler (Bugs)
- Sollten durch besseren Code vermieden werden
// NullPointerException -- Programmierfehler
String name = null;
name.length(); // NullPointerException!
// Besser: null pruefen
if (name != null) {
name.length();
}
// NumberFormatException -- ungueltige Eingabe
int zahl = Integer.parseInt("abc"); // NumberFormatException!
// Besser: Eingabe validieren oder Exception fangen
Checked Exceptions
- Muessen gefangen oder weitergegeben werden
- Entstehen durch aeussere Faktoren (Datei, Netzwerk, Datenbank)
- Der Compiler erzwingt die Behandlung
import java.io.FileReader;
// FEHLER: FileNotFoundException ist eine Checked Exception
// FileReader reader = new FileReader("datei.txt"); // Kompilierfehler!
// RICHTIG: Exception behandeln
try {
var reader = new FileReader("datei.txt");
} catch (FileNotFoundException e) {
System.out.println("Datei nicht gefunden!");
}
Vergleich
| Eigenschaft | Checked | Unchecked |
|---|---|---|
| Erbt von | Exception | RuntimeException |
| Fangen Pflicht? | Ja | Nein |
| Ursache | Aeussere Faktoren | Programmierfehler |
| Beispiele | IOException, SQLException | NullPointerException, IllegalArgumentException |
| Verhindern durch | Exception Handling | Besseren Code |
Die haeufigsten Exceptions
NullPointerException (NPE)
String text = null;
text.length(); // NullPointerException!
// Seit Java 14: Hilfreichere Fehlermeldung
// Cannot invoke "String.length()" because "text" is null
ArrayIndexOutOfBoundsException
int[] zahlen = {1, 2, 3};
zahlen[3]; // ArrayIndexOutOfBoundsException! (Index 0-2 gueltig)
NumberFormatException
Integer.parseInt("abc"); // NumberFormatException!
Integer.parseInt("12.5"); // NumberFormatException! (kein int)
IllegalArgumentException
// Wird oft in eigenen Methoden geworfen
public void setAlter(int alter) {
if (alter < 0 || alter > 150) {
throw new IllegalArgumentException("Ungueltiges Alter: " + alter);
}
this.alter = alter;
}
ArithmeticException
int ergebnis = 10 / 0; // ArithmeticException: / by zero
ClassCastException
Object obj = "Hallo";
Integer zahl = (Integer) obj; // ClassCastException!
// Besser: instanceof pruefen
if (obj instanceof Integer i) {
System.out.println(i);
}
Exceptions werfen
Du kannst selbst Exceptions werfen mit throw:
public class Bankkonto {
private double kontostand;
public void abheben(double betrag) {
if (betrag <= 0) {
throw new IllegalArgumentException("Betrag muss positiv sein!");
}
if (betrag > kontostand) {
throw new IllegalStateException("Nicht genug Guthaben! Verfuegbar: " + kontostand);
}
kontostand -= betrag;
}
}
throw vs. throws
| Schluesselwort | Bedeutung | Verwendung |
|---|---|---|
throw | Exception werfen | Im Methoden-Koerper |
throws | Exception deklarieren | In der Methodensignatur |
// throw: Exception WERFEN
public void methode() {
throw new RuntimeException("Etwas ist schiefgelaufen!");
}
// throws: Exception DEKLARIEREN (bei Checked Exceptions)
public void leseDatei(String pfad) throws IOException {
var reader = new FileReader(pfad);
// ...
}
Vergleich mit Python
# Python: try/except
try:
zahl = int("abc")
except ValueError as e:
print(f"Fehler: {e}")
# Python: raise
def set_alter(alter):
if alter < 0:
raise ValueError("Alter darf nicht negativ sein!")
// Java: try/catch
try {
var zahl = Integer.parseInt("abc");
} catch (NumberFormatException e) {
System.out.println("Fehler: " + e.getMessage());
}
// Java: throw
void setAlter(int alter) {
if (alter < 0) {
throw new IllegalArgumentException("Alter darf nicht negativ sein!");
}
}
| Python | Java |
|---|---|
try/except | try/catch |
raise | throw |
Exception | Exception |
| Keine Checked Exceptions | Checked + Unchecked |
Wann welche Exception verwenden?
| Situation | Exception | Typ |
|---|---|---|
| Ungueltiger Parameter | IllegalArgumentException | Unchecked |
| null wo es nicht sein darf | NullPointerException | Unchecked |
| Ungueltiger Zustand | IllegalStateException | Unchecked |
| Index ausserhalb | IndexOutOfBoundsException | Unchecked |
| Nicht unterstuetzte Operation | UnsupportedOperationException | Unchecked |
| Datei nicht gefunden | FileNotFoundException | Checked |
| IO-Fehler | IOException | Checked |
| Datenbank-Fehler | SQLException | Checked |
Uebungen
Uebung 1: Exceptions provozieren
Schreibe Code, der absichtlich folgende Exceptions ausloest: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException, NumberFormatException.
Uebung 2: Eingabe-Validierung
Schreibe eine Methode parseAlter(String eingabe), die einen String in ein Alter (int, 0-150) umwandelt und bei ungueltiger Eingabe eine passende Exception mit klarer Fehlermeldung wirft.
Uebung 3: Exception-Typen
Ordne die folgenden Szenarien der richtigen Exception zu: Division durch 0, null-Objekt nutzen, Datei oeffnen die nicht existiert, Array-Index zu gross.
Uebung 4: Fehlerhafte Methode reparieren
Gegeben:
static int teile(int a, int b) {
return a / b;
}
Mache die Methode sicher, indem du bei b == 0 eine aussagekraeftige Exception wirfst.
Was kommt als Naechstes?
In der naechsten Lektion lernst du try/catch/finally — wie du Exceptions auffaengst und sinnvoll behandelst, ohne dass dein Programm abstuerzt.
Zusammenfassung
- Exceptions sind Objekte, die Fehler repraesentieren
- Checked Exceptions muessen gefangen werden (Compiler erzwingt es)
- Unchecked Exceptions (RuntimeException) sind optional zu fangen
throwwirft eine Exception,throwsdeklariert sie- Die haeufigsten Exceptions:
NullPointerException,IllegalArgumentException,IOException - Unchecked Exceptions vermeidest du durch besseren Code (null-Pruefungen, Bounds-Checks)
- Verwende
IllegalArgumentExceptionfuer ungueltige Parameter in eigenen Methoden
Pro-Tipp: Seit Java 14 sind NullPointerException-Meldungen viel hilfreicher. Statt nur “NullPointerException” sagt Java jetzt genau, welche Variable null war: Cannot invoke "String.length()" because "name" is null. Stelle sicher, dass du eine aktuelle Java-Version verwendest, um von diesen verbesserten Fehlermeldungen zu profitieren!