programowanieProgramista Backend

Jakie są różnice między wyjątkami checked a unchecked w Javie, jak prawidłowo projektować obsługę błędów i jakich błędów należy unikać przy ich użyciu?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W Javie wyjątki dzielą się na checked (sprawdzane) i unchecked (niezależne).

  • Checked exceptions — dziedziczą od Exception, ale nie od RuntimeException. Kompilator wymaga ich jawnej obsługi za pomocą try-catch lub zadeklarowania w throws.
  • Unchecked exceptions — dziedziczą od RuntimeException. Kompilator nie wymaga ich obowiązkowej obsługi.
public void readFile(String file) throws IOException { /* ... */ } // checked public void divide(int a, int b) { int res = a/b; } // unchecked (ArithmeticException)

Główna subtelność — checked exceptions są używane do oczekiwanych, naprawialnych sytuacji (np. błędy wejścia-wyjścia), podczas gdy unchecked — do błędów w logice programowania lub sytuacji krytycznych, z których nie można się odzyskać (np. NullPointerException).

Pytanie z podstępem

Pytanie: Czy trzeba obsłużyć lub zadeklarować w throws unchecked exception, jeśli twój metod może je wyrzucić?

Odpowiedź: Nie. Kompilator nie wymaga sprawdzania lub deklarowania nieodwracalnych (unchecked) wyjątków. Ich obsługa jest Twoją decyzją; można użyć try-catch, ale częściej — pozwolić im „upaść” aż do globalnego handlera.

public void foo() { throw new IllegalArgumentException(); } // Nie wymaga obsługi ani deklaracji

Przykłady rzeczywistych błędów z braku znajomości subtelności tematu


Historia

W projekcie API bankowego przy obsłudze błędów wejścia-wyjścia rzucano RuntimeException zamiast checked. W rezultacie klienci nie byli zmuszeni ich obsługiwać, co prowadziło do niewłaściwego działania przy utracie połączenia z serwerem, a aplikacja „upadała” bez informowania użytkownika.


Historia

Programista zadeklarował nadmiar throws Exception w sygnaturze metod (np. bazy danych), przez co wszystkie używane metody wyżej były zmuszone do try-catch lub też throws. To zanieczyściło kod, pogorszyło czytelność i utrudniło refaktoryzację.


Historia

W jednej z mikroserwisów łapano wszystkie wyjątki za pomocą ogólnego catch (Exception e). To przechwytywało również unchecked exception’y (np. NullPointerException), co prowadziło do „cichego” ignorowania krytycznych błędów — serwis działał z niepoprawnymi danymi.