Menu
Coddy logo textTech

Checked vs. Unchecked Errors

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

Sie haben gesehen, dass sich die Exception-Hierarchie von Java in verschiedene Zweige aufteilt. Der entscheidende Unterschied, den Sie verstehen müssen, besteht zwischen checked und unchecked Exceptions – dies beeinflusst, wie Sie diese in Ihrem Code behandeln müssen.

Geprüfte Exceptions sind Exceptions, die der Compiler dich zu behandeln zwingt. Sie erweitern Exception direkt (nicht über RuntimeException). Du musst sie entweder abfangen oder mit throws deklarieren:

// Muss IOException behandeln - es ist eine Checked Exception
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);  // Kann IOException auslösen
}

// Oder sie abfangen
public void readFileSafe(String path) {
    try {
        FileReader reader = new FileReader(path);
    } catch (IOException e) {
        System.out.println("File error: " + e.getMessage());
    }
}

Unchecked Exceptions erweitern RuntimeException. Der Compiler verlangt nicht, dass Sie diese behandeln – sie weisen in der Regel auf Programmierfehler wie Null-Referenzen oder ungültigen Array-Zugriff hin:

// Keine throws-Deklaration erforderlich
public int divide(int a, int b) {
    return a / b;  // Kann ArithmeticException auslösen (unchecked)
}

String name = null;
name.length();  // NullPointerException (unchecked)

Wählen Sie beim Erstellen benutzerdefinierter Exceptions die Basisklasse basierend darauf aus, wie die Aufrufer damit umgehen sollen. Verwenden Sie Checked Exceptions für behebbare Bedingungen, die der Aufrufer vorhersehen sollte. Verwenden Sie Unchecked Exceptions für Programmierfehler, die in korrektem Code nicht auftreten sollten.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Altersverifizierungssystem bauen, das den Hauptunterschied zwischen geprüften (checked) und ungeprüften (unchecked) Ausnahmen demonstriert! Sie werden benutzerdefinierte Ausnahmen beider Typen erstellen und sehen, wie der Compiler sie unterschiedlich behandelt.

Sie werden Ihren Code über vier Dateien organisieren:

  • InvalidAgeException.java: Erstellen Sie eine geprüfte Ausnahme (checked exception) für Fehler bei der Altersvalidierung. Diese Ausnahme sollte direkt Exception erweitern, was bedeutet, dass Aufrufer gezwungen sind, sie zu behandeln. Fügen Sie einen Konstruktor hinzu, der eine Nachricht akzeptiert und diese an die Elternklasse weitergibt.
  • NegativeAgeException.java: Erstellen Sie eine ungeprüfte Ausnahme (unchecked exception) für den Fall, dass jemand ein negatives Alter angibt (ein Programmierfehler, der bei korrekter Eingabe nicht auftreten sollte). Diese sollte RuntimeException erweitern. Fügen Sie einen Konstruktor hinzu, der eine Nachricht akzeptiert und an die Elternklasse weitergibt.
  • AgeVerifier.java: Erstellen Sie eine Klasse, die Alter unter Verwendung beider Ausnahmetypen validiert. Fügen Sie zwei statische Methoden hinzu:

    verifyAge(int age) - Diese Methode sollte eine NegativeAgeException (ungeprüft) mit der Nachricht "Age cannot be negative: " + age werfen, wenn das Alter kleiner als 0 ist. Wenn das Alter kleiner als 18 ist, werfen Sie eine InvalidAgeException (geprüft) mit der Nachricht "Must be 18 or older: " + age. Andernfalls geben Sie "Age " + age + " verified successfully" aus. Da diese Methode eine geprüfte Ausnahme wirft, müssen Sie sie mit throws InvalidAgeException deklarieren.

    verifyAgeUncheckedOnly(int age) - Diese Methode verwendet nur ungeprüfte Ausnahmen. Wenn das Alter negativ ist, werfen Sie eine NegativeAgeException mit demselben Nachrichtenformat. Wenn das Alter kleiner als 18 ist, werfen Sie eine IllegalArgumentException mit der Nachricht "Too young: " + age. Andernfalls geben Sie "Age " + age + " verified (unchecked method)" aus. Beachten Sie, dass diese Methode keine throws-Deklaration benötigt!

  • Main.java: Führen Sie Ihr Verifizierungssystem zusammen! Sie erhalten eine Eingabe: ein Alter (Ganzzahl).

    Geben Sie zuerst "=== Checked Exception Method ===" aus und rufen Sie verifyAge mit dem eingegebenen Alter auf. Da sie eine geprüfte Ausnahme wirft, müssen Sie sie in einen try-catch-Block einschließen. Fangen Sie InvalidAgeException ab und geben Sie "Checked exception caught: " + e.getMessage() aus. Fangen Sie auch NegativeAgeException ab und geben Sie "Unchecked exception caught: " + e.getMessage() aus.

    Geben Sie dann eine Leerzeile und "=== Unchecked Exception Method ===" aus. Rufen Sie verifyAgeUncheckedOnly mit demselben Alter auf. Obwohl diese Methode Ausnahmen werfen kann, sind Sie nicht gezwungen, sie abzufangen. Schließen Sie sie jedoch trotzdem in einen try-catch-Block ein, um Fehler elegant zu behandeln. Fangen Sie NegativeAgeException ab und geben Sie "Runtime exception caught: " + e.getMessage() aus. Fangen Sie IllegalArgumentException ab und geben Sie "Illegal argument caught: " + e.getMessage() aus.

Sie erhalten eine Eingabe: eine Ganzzahl, die das zu verifizierende Alter darstellt.

Beachten Sie den Hauptunterschied: Die Methode mit der geprüften Ausnahme erfordert eine throws-Deklaration und zwingt Aufrufer, sie zu behandeln, während die ungeprüfte Methode ohne jegliche Ausnahmebehandlung einwandfrei kompiliert. Dies ist die grundlegende Unterscheidung zwischen geprüften und ungeprüften Ausnahmen in Java!

Spickzettel

Java-Exceptions werden in geprüfte (checked) und ungeprüfte (unchecked) Exceptions unterteilt, was bestimmt, wie der Compiler deren Behandlung erzwingt.

Geprüfte Exceptions erweitern Exception direkt (nicht über RuntimeException). Der Compiler zwingt Sie dazu, diese entweder abzufangen oder mit throws zu deklarieren:

// Muss mit throws deklariert werden
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);
}

// 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 Exceptions erweitern RuntimeException. Der Compiler verlangt nicht, dass Sie diese behandeln. Sie weisen in der Regel auf Programmierfehler hin:

// Keine throws-Deklaration erforderlich
public int divide(int a, int b) {
    return a / b;  // Kann ArithmeticException auslösen (ungeprüft)
}

String name = null;
name.length();  // NullPointerException (ungeprüft)

Wählen Sie beim Erstellen benutzerdefinierter Exceptions die Basisklasse basierend darauf aus, wie Aufrufer damit umgehen sollten:

  • Verwenden Sie geprüfte Exceptions (erweitern Exception) für behebbare Zustände, die der Aufrufer vorhersehen sollte
  • Verwenden Sie ungeprüfte Exceptions (erweitern RuntimeException) für Programmierfehler, die in korrektem Code nicht auftreten sollten

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: Teste die Methode für geprüfte Ausnahmen (Checked Exceptions)
        // Drucke: "=== Checked Exception Method ==="
        // Rufe AgeVerifier.verifyAge(age) in einem try-catch-Block auf
        // - Catch InvalidAgeException: drucke "Checked exception caught: [message]"
        // - Catch NegativeAgeException: drucke "Unchecked exception caught: [message]"
        
        
        // TODO: Drucke eine Leerzeile, dann "=== Unchecked Exception Method ==="
        // Rufe AgeVerifier.verifyAgeUncheckedOnly(age) in einem try-catch-Block auf
        // - Catch NegativeAgeException: drucke "Runtime exception caught: [message]"
        // - Catch IllegalArgumentException: drucke "Illegal argument caught: [message]"
        
    }
}
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