Menu
Coddy logo textTech

Exception-Klassenhierarchie

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 59 von 87.

Javas System zur Ausnahmebehandlung basiert auf einer gut organisierten Klassenhierarchie, deren Wurzel die Klasse Throwable ist. Das Verständnis dieser Hierarchie hilft dir, Ausnahmen effektiver abzufangen und zu behandeln.

An der Spitze steht Throwable, der Elternteil aller Ausnahmen und Fehler. Es hat zwei direkte Unterklassen:

Throwable
├── Error          // Schwere Probleme (diese nicht abfangen)
└── Exception      // Behebbare Probleme
    └── RuntimeException  // Ungeprüfte Exceptions

Fehler steht für schwerwiegende Probleme, die Anwendungen nicht zu behandeln versuchen sollten, wie etwa OutOfMemoryError oder StackOverflowError. Diese weisen auf grundlegende Probleme mit der JVM selbst hin.

Exception ist der Zweig, mit dem du am häufigsten arbeiten wirst. Er teilt sich in zwei Kategorien: geprüfte Ausnahmen (direkte Unterklassen von Exception) und ungeprüfte Ausnahmen (Unterklassen von RuntimeException).

// Häufige Exception-Klassen
Exception
├── IOException           // Datei-/Netzwerkprobleme
├── SQLException          // Datenbankprobleme
└── RuntimeException
    ├── NullPointerException
    ├── ArrayIndexOutOfBoundsException
    └── IllegalArgumentException

Da exceptions classes sind, folgen sie den Vererbungsregeln. Wenn du einen übergeordneten exception-Typ abfängst, fängst du auch alle seine untergeordneten Typen ab:

try {
    // etwas Code
} catch (Exception e) {
    // Fängt ALLE Exceptions ab (normalerweise zu breit)
}
try {
    // etwas Code
} catch (RuntimeException e) {
    // Catches only runtime exceptions and subclasses
}

Diese hierarchy ermöglicht es dir, beim Behandeln von Fehlern so spezifisch oder allgemein wie nötig zu sein, und sie bildet die Grundlage für das Erstellen eigener benutzerdefinierter exceptions.

challenge icon

Aufgabe

Einfach

Erstelle einen ExceptionAnalyzer, der zeigt, wie die Exception-Hierarchie von Java in der Praxis funktioniert! Du erstellst ein System, das exceptions auf verschiedenen Ebenen der Spezifität abfängt und meldet, welcher Typ Caught wurde.

Du organisierst deinen Code auf drei Dateien:

  • ExceptionThrower.java: Erstelle eine Klasse, die abhängig von der Eingabe verschiedene exceptions auslösen kann. Deine Klasse sollte drei statische Methoden enthalten:

    triggerRuntime(String type) – Löse abhängig vom type-String verschiedene Runtime-exceptions aus:

    • Wenn type "null" ist, löse eine NullPointerException mit der Message "Null value encountered" aus
    • Wenn type "index" ist, löse eine ArrayIndexOutOfBoundsException mit der Message "Invalid index" aus
    • Wenn type "argument" ist, löse eine IllegalArgumentException mit der Message "Bad argument" aus

    triggerArithmetic() – Löse eine ArithmeticException mit der Message "Division error" aus

    triggerGeneric() – Löse eine IllegalStateException mit der Message "Generic runtime error" aus (ihre Hierarchie ist Exception > RuntimeException > IllegalStateException)

  • ExceptionAnalyzer.java: Erstelle eine Klasse, die exceptions auf verschiedenen Ebenen der Hierarchie abfängt und erkennt, was Caught wurde. Füge diese statischen Methoden hinzu:

    analyzeSpecific(String type) – Rufe ExceptionThrower.triggerRuntime(type) innerhalb eines try-Blocks auf. Verwende separate catch-Blöcke für NullPointerException, ArrayIndexOutOfBoundsException und IllegalArgumentException. Gib für jeden aus: Caught specific: [exception class simple name], gefolgt von Message: [exception message]

    analyzeWithParent() – Rufe ExceptionThrower.triggerArithmetic() innerhalb eines try-Blocks auf. Fange sie mithilfe von RuntimeException (dem übergeordneten Typ) ab. Gib Caught via parent: RuntimeException aus, gefolgt von Actual type: [exception class simple name]

    analyzeWithGrandparent() – Rufe ExceptionThrower.triggerGeneric() innerhalb eines try-Blocks auf. Fange sie mithilfe von Exception ab (noch höher in der Hierarchie). Gib Caught via grandparent: Exception aus, gefolgt von Actual type: [exception class simple name]

  • Main.java: Führe deinen ExceptionAnalyzer zusammen! Du erhältst eine Eingabe: einen Exception-Typ-String (entweder "null", "index" oder "argument").

    Gib zuerst === Specific Catch === aus und rufe analyzeSpecific mit deiner Eingabe auf.

    Gib dann eine leere Zeile und === Parent Catch === aus und rufe analyzeWithParent auf.

    Gib schließlich eine leere Zeile und === Grandparent Catch === aus und rufe analyzeWithGrandparent auf.

Du erhältst eine Eingabe: den auszulösenden Exception-Typ ("null", "index" oder "argument").

Verwende e.getClass().getSimpleName(), um den Klassennamen der Exception zu erhalten, und e.getMessage(), um ihre Message abzurufen. Diese Herausforderung zeigt, dass das Abfangen eines übergeordneten Exception-Typs auch alle seine untergeordneten Typen abfängt – ein wichtiges Konzept bei der Entscheidung, wie spezifisch deine Behandlung von exceptions sein sollte!

Probier es selbst

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String type = scanner.nextLine();
        
        // TODO: Print "=== Specific Catch ===" and call ExceptionAnalyzer.analyzeSpecific(type)
        
        // TODO: Gib eine leere Zeile aus, dann "=== Parent Catch ===", dann rufe ExceptionAnalyzer.analyzeWithParent() auf
        
        // TODO: Print a blank line, then "=== Grandparent Catch ===", then call ExceptionAnalyzer.analyzeWithGrandparent()
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Java-Compiler