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.
Wyzwanie
ŁatwyStwó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 wypiszAge [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śNegativeAgeExceptionz takim samym formatem komunikatu. Jeśli wiek jest mniejszy niż 18, zgłoś wyjątekIllegalArgumentExceptionz komunikatem"Too young: [age]". W przeciwnym razie wypiszAge [age] verified (unchecked method). Zauważ, że ta metoda nie wymaga deklaracjithrows!Main.java: Połącz swój system weryfikacji! Otrzymasz jedno wejście: wiek (liczbę całkowitą).Najpierw wypisz
=== Checked Exception Method ===i wywołajverifyAge, przekazując podany wiek. Ponieważ metoda zgłasza wyjątek sprawdzany, musisz umieścić ją w bloku try-catch. PrzechwyćInvalidAgeExceptioni wypiszChecked exception caught: [message]. Przechwyć teżNegativeAgeExceptioni wypiszUnchecked exception caught: [message].Następnie wypisz pustą linię i
=== Unchecked Exception Method ===. WywołajverifyAgeUncheckedOnly, 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ćNegativeAgeExceptioni wypiszRuntime exception caught: [message]. PrzechwyćIllegalArgumentExceptioni wypiszIllegal 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]"
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online