Geprüfte vs. ungeprüfte Fehler
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 61 von 87.
Du hast gesehen, dass die Ausnahmehierarchie von Java in verschiedene Zweige aufgeteilt ist. Der entscheidende Unterschied, den du verstehen musst, besteht zwischen geprüften und ungeprüften Ausnahmen. Dies beeinflusst, wie du sie in deinem Code behandeln musst.
Geprüfte Ausnahmen sind Ausnahmen, deren Behandlung der Compiler erzwingt. Sie erweitern Exception direkt (nicht über RuntimeException). Du musst sie entweder abfangen oder mit throws deklarieren:
// Muss IOException behandeln - es ist checked
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path); // Kann IOException werfen
}
// Oder abfangen
public void readFileSafe(String path) {
try {
FileReader reader = new FileReader(path);
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
}
}Ungeprüfte Ausnahmen erweitern RuntimeException. Der Compiler verlangt nicht, dass du sie behandelst. Sie weisen typischerweise auf Programmierfehler wie Nullreferenzen oder ungültigen Array-Zugriff hin:
// Keine throws-Deklaration nötig
public int divide(int a, int b) {
return a / b; // Kann ArithmeticException werfen (unchecked)
}
String name = null;
name.length(); // NullPointerException (unchecked)Wähle beim Erstellen benutzerdefinierter Ausnahmen die übergeordnete Klasse danach aus, wie aufrufender Code sie behandeln soll. Verwende geprüfte Ausnahmen für behebbare Bedingungen, mit denen der aufrufende Code rechnen sollte. Verwende ungeprüfte Ausnahmen für Programmierfehler, die in korrekt geschriebenem Code nicht auftreten sollten.
Aufgabe
EinfachErstellen wir ein System zur Altersüberprüfung, das den entscheidenden Unterschied zwischen geprüften und ungeprüften Ausnahmen demonstriert! Du wirst benutzerdefinierte Ausnahmen beider Arten erstellen und sehen, wie der Compiler sie unterschiedlich behandelt.
Du wirst deinen Code auf vier Dateien verteilen:
InvalidAgeException.java: Erstelle eine geprüfte Ausnahme für Fehler bei der Altersüberprüfung. Diese Ausnahme sollte direkt vonExceptionerben, was bedeutet, dass Aufrufer gezwungen werden, sie zu behandeln. Füge einen Konstruktor hinzu, der eine Nachricht akzeptiert und sie an die übergeordnete Klasse weitergibt.NegativeAgeException.java: Erstelle eine ungeprüfte Ausnahme für den Fall, dass jemand ein negatives Alter angibt (ein Programmierfehler, der bei korrekter Eingabe nicht auftreten sollte). Diese sollte vonRuntimeExceptionerben. Füge einen Konstruktor hinzu, der eine Nachricht akzeptiert und an die übergeordnete Klasse weitergibt.AgeVerifier.java: Erstelle eine Klasse, die Alter mithilfe beider Ausnahmetypen überprüft. Füge zwei statische Methoden hinzu:verifyAge(int age)– Diese Methode sollteNegativeAgeException(ungeprüft) mit der Nachricht"Age cannot be negative: [age]"auslösen, wenn das Alter kleiner als 0 ist. Wenn das Alter kleiner als 18 ist, löseInvalidAgeException(geprüft) mit der Nachricht"Must be 18 or older: [age]"aus. Andernfalls gibAge [age] verified successfullyaus. Da diese Methode eine geprüfte Ausnahme auslöst, musst du sie mitthrows InvalidAgeExceptiondeklarieren.verifyAgeUncheckedOnly(int age)– Diese Methode verwendet nur ungeprüfte Ausnahmen. Wenn das Alter negativ ist, löseNegativeAgeExceptionmit demselben Nachrichtenformat aus. Wenn das Alter kleiner als 18 ist, löse eineIllegalArgumentExceptionmit der Nachricht"Too young: [age]"aus. Andernfalls gibAge [age] verified (unchecked method)aus. Beachte, dass diese Methode keinethrows-Deklaration benötigt!Main.java: Führe dein Überprüfungssystem zusammen! Du erhältst eine Eingabe: ein Alter (eine Ganzzahl).Gib zuerst
=== Checked Exception Method ===aus und rufeverifyAgemit dem eingegebenen Alter auf. Da die Methode eine geprüfte Ausnahme auslöst, musst du sie in einen Try-Catch-Block einschließen. FangeInvalidAgeExceptionab und gibChecked exception caught: [message]aus. Fange außerdemNegativeAgeExceptionab und gibUnchecked exception caught: [message]aus.Gib anschließend eine leere Zeile und
=== Unchecked Exception Method ===aus. RufeverifyAgeUncheckedOnlymit demselben Alter auf. Obwohl diese Methode Ausnahmen auslösen kann, bist du nicht gezwungen, sie abzufangen. Schließe sie dennoch in einen Try-Catch-Block ein, um Fehler ordnungsgemäß zu behandeln. FangeNegativeAgeExceptionab und gibRuntime exception caught: [message]aus. FangeIllegalArgumentExceptionab und gibIllegal argument caught: [message]aus.
Du erhältst eine Eingabe: eine Ganzzahl, die das zu überprüfende Alter darstellt.
Beachte den entscheidenden Unterschied: Die Methode mit der geprüften Ausnahme erfordert eine throws-Deklaration und zwingt Aufrufer, sie zu behandeln, während die ungeprüfte Methode auch ohne Ausnahmebehandlung problemlos kompiliert. Das ist der grundlegende Unterschied zwischen geprüften und ungeprüften Ausnahmen in Java!
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int age = scanner.nextInt();
// TODO: Test the checked exception method
// Print: "=== Checked Exception Method ==="
// Rufe AgeVerifier.verifyAge(age) in einem try-catch auf
// - Catch InvalidAgeException: print "Checked exception caught: [message]"
// - Catch NegativeAgeException: print "Unchecked exception caught: [message]"
// TODO: Print a blank line, then "=== Unchecked Exception Method ==="
// Rufe AgeVerifier.verifyAgeUncheckedOnly(age) in einem try-catch auf
// - Catch NegativeAgeException: print "Runtime exception caught: [message]"
// - Catch IllegalArgumentException: print "Illegal argument caught: [message]"
}
}
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