1. Po co jest potrzebny try-catch?
Jak już wiesz, w programowaniu błędy zdarzają się cały czas: dzielenie przez zero, nieprawidłowe dane wejściowe, brak pliku itd. Jeśli takich sytuacji nie obsłużysz, program zakończy się błędem (awaryjnie).
Konstrukcja try-catch pozwala „złapać” wyjątek i zapobiec awarii programu, starannie obsługując błąd.
Składnia konstrukcji try-catch
try
{
// Kod, który może zgłosić wyjątek
}
catch (ExceptionType variableName)
{
// Kod do obsługi wyjątku
}
Wyjaśnienie:
- try — „spróbuj wykonać ten kod”.
- catch — „jeśli wystąpi wyjątek wskazanego typu, obsłuż go tutaj”.
Jak to działa?
Jeśli w bloku try pojawi się wyjątek, wykonywanie tego bloku zostaje natychmiast przerwane, a sterowanie przechodzi do pierwszego pasującego bloku catch. Jeśli wyjątek nie wystąpi — blok catch jest pomijany.
2. Przykład: dzielenie przez zero
Bez obsługi wyjątków
int a = 10;
int b = 0;
int result = a / b; // Tutaj program zakończy się błędem!
System.out.println("Wynik: " + result); // Do tego miejsca nie dojdziemy
Wynik:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:3)
Z obsługą przez try-catch
int a = 10;
int b = 0;
try
{
int result = a / b; // Tutaj może wystąpić wyjątek
System.out.println("Wynik: " + result);
}
catch (ArithmeticException e)
{
System.out.println("Błąd: dzielenie przez zero jest niemożliwe!");
}
System.out.println("Program kontynuuje działanie.");
Wynik:
Błąd: dzielenie przez zero jest niemożliwe!
Program kontynuuje działanie.
Wyjaśnienie:
- Gdy tylko Java napotka dzielenie przez zero, „zgłasza” wyjątek.
- try zostaje przerwany, a sterowanie przechodzi do catch.
- Po obsłużeniu błędu program kontynuuje wykonywanie.
3. Jak działa blok catch
W nawiasach po catch podaje się typ wyjątku (np. ArithmeticException) oraz nazwę zmiennej (zwykle e).
Wewnątrz bloku catch można uzyskać szczegóły błędu:
- e.getMessage() — krótki opis błędu.
- e.printStackTrace() — szczegółowe informacje (do debugowania).
Przykład:
try
{
int[] arr = new int[2];
int x = arr[10]; // Błąd: brak takiego indeksu
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("Błąd: " + e.getMessage()); // Wypisujemy komunikat błędu
e.printStackTrace(); // Wypisujemy w konsoli wszystkie informacje o błędzie
}
4. Przepływ wykonania przy wyjątku
Jeśli w bloku try nie ma błędów — blok catch zostaje pominięty.
Jeśli w bloku try wystąpi błąd — wykonywanie bloku zostaje przerwane w miejscu błędu, a sterowanie natychmiast przechodzi do pierwszego pasującego catch. Wszystko, co jest po miejscu błędu w try, już się nie wykona!
Ilustracja:
try
{
System.out.println("1. Początek try");
int a = 10 / 0; // Błąd!
System.out.println("2. Po dzieleniu"); // Nie wykona się
}
catch (ArithmeticException e)
{
System.out.println("3. W bloku catch");
}
System.out.println("4. Po try-catch");
Wynik:
1. Początek try
3. W bloku catch
4. Po try-catch
5. Typowe błędy przy używaniu try-catch
Błąd nr 1: Zbyt szeroki catch.
Jeśli użyjesz catch (Exception e), możesz przechwycić mnóstwo nieoczekiwanych błędów, których nie potrafisz poprawnie obsłużyć.
Rozwiązanie: łap tylko te wyjątki, których rzeczywiście można się spodziewać w danym miejscu (np. IOException, SQLException).
Błąd nr 2: Pusty catch.
Pisanie catch (Exception e) {} — to ukrywanie problemu. Program może się wywrócić w innym miejscu albo zachowywać się dziwnie.
Rozwiązanie: przynajmniej zaloguj błąd (e.printStackTrace() albo logger).
Błąd nr 3: Wiara, że try-catch naprawi każdy problem.
Jeśli błąd jest w logice programu (np. dzielenie przez zero, błędny algorytm) — żaden try-catch nie pomoże.
Rozwiązanie: używaj try-catch tylko do rzeczywiście przewidywanych sytuacji, a nie do maskowania błędów.
GO TO FULL VERSION