Hierarchie der Exception-Klassen
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 ExceptionsFehler 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
└── IllegalArgumentExceptionDa 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 Hierarchie ermöglicht es dir, bei der Fehlerbehandlung so spezifisch oder allgemein vorzugehen, wie es nötig ist, und sie bildet die Grundlage für die Erstellung deiner eigenen benutzerdefinierten Ausnahmen.
Aufgabe
EinfachLass uns einen Exception-Analyzer erstellen, der zeigt, wie die Exception-Hierarchie von Java in der Praxis funktioniert! Du erstellst ein System, das Exceptions auf unterschiedlichen Ebenen der Spezifität abfängt und meldet, welcher Typ abgefangen wurde.
Du organisierst deinen Code über drei Dateien:
ExceptionThrower.java: Erstelle eine Klasse, die abhängig von der Eingabe verschiedene Exception-Typen auslösen kann. Deine Klasse sollte drei statische Methoden enthalten:triggerRuntime(String type)– Wirf abhängig vom Typ-String verschiedene Runtime-Exceptions:- Wenn type
"null"ist, wirf eineNullPointerExceptionmit der Nachricht"Null value encountered" - Wenn type
"index"ist, wirf eineArrayIndexOutOfBoundsExceptionmit der Nachricht"Invalid index" - Wenn type
"argument"ist, wirf eineIllegalArgumentExceptionmit der Nachricht"Bad argument"
triggerArithmetic()– Wirf eineArithmeticExceptionmit der Nachricht"Division error"triggerGeneric()– Wirf eineIllegalStateExceptionmit der Nachricht"Generic runtime error"(ihre Hierarchie ist Exception > RuntimeException > IllegalStateException)- Wenn type
ExceptionAnalyzer.java: Erstelle eine Klasse, die Exceptions auf unterschiedlichen Ebenen der Hierarchie abfängt und erkennt, was abgefangen wurde. Füge diese statischen Methoden hinzu:analyzeSpecific(String type)– RufeExceptionThrower.triggerRuntime(type)innerhalb eines try-Blocks auf. Verwende separate catch-Blöcke fürNullPointerException,ArrayIndexOutOfBoundsExceptionundIllegalArgumentException. Gib für jeden aus:Caught specific: [exception class simple name], gefolgt vonMessage: [exception message]analyzeWithParent()– RufeExceptionThrower.triggerArithmetic()innerhalb eines try-Blocks auf. Fange sie mitRuntimeException(dem übergeordneten Typ) ab. GibCaught via parent: RuntimeExceptionaus, gefolgt vonActual type: [exception class simple name]analyzeWithGrandparent()– RufeExceptionThrower.triggerGeneric()innerhalb eines try-Blocks auf. Fange sie mitException(weiter oben in der Hierarchie) ab. GibCaught via grandparent: Exceptionaus, gefolgt vonActual type: [exception class simple name]Main.java: Führe deinen Exception-Analyzer zusammen! Du erhältst eine Eingabe: einen Exception-Typ-String (entweder"null","index"oder"argument").Gib zuerst
=== Specific Catch ===aus und rufeanalyzeSpecificmit deiner Eingabe auf.Gib dann eine leere Zeile und
=== Parent Catch ===aus und rufeanalyzeWithParentauf.Gib schließlich eine leere Zeile und
=== Grandparent Catch ===aus und rufeanalyzeWithGrandparentauf.
Du erhältst eine Eingabe: den auszulösenden Exception-Typ ("null", "index" oder "argument").
Verwende e.getClass().getSimpleName(), um den Klassennamen der Exception abzurufen, und e.getMessage(), um ihre Nachricht 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 dein Exception-Handling 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()
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenFelder (Attribute)KonstruktormethodeÜberladen von KonstruktorenRückblick – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbung (extends)Das Schlüsselwort superÜberschreiben von Methoden (@Override)KonstruktorverkettungDie Object-KlasseEinfach- und mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenRückblick – Mitarbeiterhierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-SchnittstelleRückblick – Benutzerdefinierte Sortierung10Exception Handling in OOP
Hierarchie der Exception-KlassenBenutzerdefinierte ExceptionsGeprüfte vs. ungeprüfte FehlerTry-with-Resources-MusterRückblick – Validierter Benutzer2Zugriffsmodifikatoren & Kapselung
Übersicht der ZugriffsebenenGetter- und Setter-MethodenInformationsverbergungDas Schlüsselwort finalRückblick – Bankkontoverwaltung5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenRückblick – Formrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, verschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Versiegelte Klassen (Java 17+)11Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBuilder-MusterObserver-MusterStrategie-Muster14Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungsdienst3Klassen-Props & statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Wiederholung – Counter & Utility6Schnittstellen & abstrakte Klassen
Einführung in InterfacesInterfaces implementierenMehrere Interfaces implementierenDefault & Static in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesRückblick – ZahlungssystemÜbe selbstständig: Online-Java-Compiler