Menu
Coddy logo textTech

Błędy sprawdzane a niesprawdzane

Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 61 z 87.

Widzisz już, że hierarchia wyjątków w Javie dzieli się na różne gałęzie. Kluczowe rozróżnienie, które musisz zrozumieć, dotyczy wyjątków kontrolowanych i niekontrolowanych. Wpływa ono na to, jak musisz obsługiwać je w swoim kodzie.

Wyjątki sprawdzane to wyjątki, których obsługę wymusza kompilator. Rozszerzają bezpośrednio Exception (nie przez RuntimeException). Musisz je przechwycić albo zadeklarować za pomocą throws:

// Trzeba obsłużyć IOException — jest wyjątkiem kontrolowanym
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);  // Może zgłosić IOException
}

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

Wyjątki niekontrolowane dziedziczą po RuntimeException. Kompilator nie wymaga ich obsługi. Zazwyczaj wskazują na błędy programistyczne, takie jak odwołania do wartości null lub nieprawidłowy dostęp do tablicy:

// Deklaracja throws nie jest wymagana
public int divide(int a, int b) {
    return a / b;  // Może zgłosić ArithmeticException (wyjątek niekontrolowany)
}

String name = null;
name.length();  // NullPointerException (wyjątek niekontrolowany)

Podczas tworzenia własnych wyjątków wybierz klasę nadrzędną w zależności od tego, jak chcesz, aby wywołujący je obsługiwali. Używaj wyjątków sprawdzanych w przypadku możliwych do odzyskania warunków, których wystąpienia wywołujący powinni się spodziewać. Używaj wyjątków niesprawdzanych w przypadku błędów programistycznych, które nie powinny występować w poprawnym kodzie.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system weryfikacji wieku, który pokazuje kluczową różnicę między wyjątkami sprawdzanymi i niesprawdzanymi! Utworzysz własne wyjątki obu typów i zobaczysz, jak kompilator traktuje je inaczej.

Rozmieścisz swój kod w czterech plikach:

  • InvalidAgeException.java: Utwórz wyjątek sprawdzany dla niepowodzeń walidacji wieku. Ten wyjątek powinien bezpośrednio rozszerzać klasę Exception, co oznacza, że wywołujący będą musieli go obsłużyć. Dodaj konstruktor, który przyjmuje komunikat i przekazuje go do klasy nadrzędnej.
  • NegativeAgeException.java: Utwórz wyjątek niesprawdzany na wypadek, gdy ktoś poda ujemny wiek (błąd programistyczny, który nie powinien wystąpić przy poprawnych danych wejściowych). Powinien rozszerzać klasę RuntimeException. Dodaj konstruktor, który przyjmuje komunikat i przekazuje go do klasy nadrzędnej.
  • AgeVerifier.java: Utwórz klasę, która weryfikuje wiek przy użyciu obu typów wyjątków. Dodaj dwie metody statyczne:

    verifyAge(int age) - Ta metoda powinna zgłaszać NegativeAgeException (niesprawdzany) z komunikatem "Age cannot be negative: [age]", jeśli wiek jest mniejszy niż 0. Jeśli wiek jest mniejszy niż 18, zgłoś InvalidAgeException (sprawdzany) z komunikatem "Must be 18 or older: [age]". W przeciwnym razie wypisz Age [age] verified successfully. Ponieważ ta metoda zgłasza wyjątek sprawdzany, musisz zadeklarować go za pomocą throws InvalidAgeException.

    verifyAgeUncheckedOnly(int age) - Ta metoda używa wyłącznie wyjątków niesprawdzanych. Jeśli wiek jest ujemny, zgłoś NegativeAgeException z takim samym formatem komunikatu. Jeśli wiek jest mniejszy niż 18, zgłoś wyjątek IllegalArgumentException z komunikatem "Too young: [age]". W przeciwnym razie wypisz Age [age] verified (unchecked method). Zauważ, że ta metoda nie wymaga deklaracji throws!

  • Main.java: Połącz swój system weryfikacji! Otrzymasz jedno wejście: wiek (liczbę całkowitą).

    Najpierw wypisz === Checked Exception Method === i wywołaj verifyAge, przekazując podany wiek. Ponieważ metoda zgłasza wyjątek sprawdzany, musisz umieścić ją w bloku try-catch. Przechwyć InvalidAgeException i wypisz Checked exception caught: [message]. Przechwyć też NegativeAgeException i wypisz Unchecked exception caught: [message].

    Następnie wypisz pustą linię i === Unchecked Exception Method ===. Wywołaj verifyAgeUncheckedOnly, przekazując ten sam wiek. Mimo że ta metoda może zgłaszać wyjątki, nie musisz ich przechwytywać. Umieść ją jednak w bloku try-catch, aby odpowiednio obsługiwać błędy. Przechwyć NegativeAgeException i wypisz Runtime exception caught: [message]. Przechwyć IllegalArgumentException i wypisz Illegal argument caught: [message].

Otrzymasz jedno wejście: liczbę całkowitą reprezentującą wiek do weryfikacji.

Zwróć uwagę na kluczową różnicę: metoda z wyjątkiem sprawdzanym wymaga deklaracji throws i zmusza wywołujących do jego obsługi, podczas gdy metoda z wyjątkiem niesprawdzanym kompiluje się bez problemu bez obsługi wyjątków. To podstawowa różnica między wyjątkami sprawdzanymi i niesprawdzanymi w Java!

Spróbuj swoich sił

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int age = scanner.nextInt();
        
        // TODO: Przetestuj metodę zgłaszającą wyjątek kontrolowany
        // Wypisz: "=== Checked Exception Method ==="
        // Wywołaj AgeVerifier.verifyAge(age) w bloku try-catch
        // - Przechwyć InvalidAgeException: wypisz "Checked exception caught: [message]"
        // - Przechwyć NegativeAgeException: wypisz "Unchecked exception caught: [message]"
        
        
        // TODO: Wypisz pustą linię, a następnie "=== Unchecked Exception Method ==="
        // Wywołaj AgeVerifier.verifyAgeUncheckedOnly(age) w bloku try-catch
        // - Przechwyć NegativeAgeException: wypisz "Runtime exception caught: [message]"
        // - Przechwyć IllegalArgumentException: wypisz "Illegal argument caught: [message]"
        
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Java online