Wyjątki i enumy w Javie: try, catch, throw
Zaktualizowano 22 października 2026
Bez wyjątków w Javie program po prostu się przerywa, gdy coś pójdzie nie tak, na przykład przy Integer.parseInt("abc"). Dzięki wyjątkom (exceptions) przechwytujesz takie błędy i na nie reagujesz albo sam zgłaszasz błąd. Do tego dochodzą enumy: typy ze stałą listą wartości, jak fazy sygnalizacji świetlnej.
Przechwytywanie wyjątków
Kod, który może się nie udać, umieszczasz w bloku try. Jeśli zostanie tam rzucony wyjątek, Java od razu przeskakuje do pasującego bloku catch. Reszta bloku try zostaje pominięta. Potem program działa normalnie dalej.
try { int value = Integer.parseInt(text);} catch (NumberFormatException e) { // text was not a number}
e.getMessage() zwraca komunikat błędu. Blok finally wykonuje się zawsze, czy się udało, czy nie, nawet jeśli w try stoi return. Umieszczasz w nim to, co musi się wydarzyć w każdym przypadku, na przykład zamknięcie połączenia.
public class Main { public static void main(String[] args) { String[] inputs = {"42", "abc", "7"}; int sum = 0; for (String input : inputs) { try { int value = Integer.parseInt(input); sum += value; System.out.println("Added " + value); } catch (NumberFormatException e) { System.out.println("Not a number: " + input); } finally { System.out.println("Checked " + input); } } System.out.println("Sum: " + sum); }}Rzucanie wyjątków i własne wyjątki
Instrukcją throw new IllegalArgumentException("No values"); sam zgłaszasz błąd. Metoda kończy się w tym miejscu, a wywołujący dostaje wyjątek.
Własny wyjątek to klasa, która dziedziczy po Exception (zobacz dziedziczenie w Javie). Jej konstruktor przekazuje komunikat dalej przez super(...). Są dwa rodzaje:
- Checked (kontrolowane): wszystko, co dziedziczy po
Exception. Kompilator wymaga, żebyś je przechwycił albo zapowiedział przezthrowsw nagłówku metody:void buyApple() throws OutOfStockException. - Unchecked (niekontrolowane): wszystko, co dziedziczy po
RuntimeException, np.IllegalArgumentExceptioniNumberFormatException. Tu kompilator niczego nie wymaga.
throws przekazuje wyjątek dalej do wywołującego. Wtedy to on musi się nim zająć.
class OutOfStockException extends Exception { public OutOfStockException(String product) { super(product + " is out of stock"); }}
class Shop { private int apples = 2;
public void buyApple() throws OutOfStockException { if (apples == 0) { throw new OutOfStockException("Apple"); } apples--; }}
public class Main { public static double divide(double a, double b) { if (b == 0) { throw new IllegalArgumentException("Cannot divide by 0"); } return a / b; }
public static void main(String[] args) { try { System.out.println(divide(10, 4)); System.out.println(divide(1, 0)); System.out.println("This line never runs"); } catch (IllegalArgumentException e) { System.out.println("Error: " + e.getMessage()); }
Shop shop = new Shop(); for (int i = 1; i <= 3; i++) { try { shop.buyApple(); System.out.println("Bought apple " + i); } catch (OutOfStockException e) { System.out.println(e.getMessage()); } } }}Enumy
enum Season { SPRING, SUMMER, AUTUMN, WINTER } tworzy typ z dokładnie czterema wartościami. Zmienna typu Season nie może zawierać niczego innego, a literówki wyłapie kompilator.
- Wartości enuma porównujesz przez
==. values()zwraca wszystkie wartości jako tablicę, w kolejności deklaracji.ordinal()to pozycja, liczona od 0.- Jako tekst wartość daje swoją nazwę, np.
SUMMER. - W
switch(zobacz instrukcje warunkowe w Javie) piszesz wartości bez nazwy klasy:case SUMMER ->.
Enum, tak jak klasa, może mieć pola, konstruktor i metody. Wartości w nawiasach po każdej stałej trafiają do konstruktora: EURO(100).
enum Season { SPRING, SUMMER, AUTUMN, WINTER}
enum Coin { CENT(1), TEN_CENTS(10), EURO(100);
private final int cents;
Coin(int cents) { this.cents = cents; }
public int getCents() { return cents; }}
public class Main { public static void main(String[] args) { Season now = Season.SUMMER; System.out.println(now); System.out.println("Position: " + now.ordinal()); System.out.println(now == Season.SUMMER);
for (Season s : Season.values()) { System.out.print(s + " "); } System.out.println();
String advice = switch (now) { case SUMMER -> "Sunscreen"; case WINTER -> "Gloves"; default -> "Umbrella"; }; System.out.println(advice);
int total = 0; for (Coin c : Coin.values()) { total += c.getCents(); } System.out.println("All coins: " + total + " cents"); }}Typowe błędy
Nieobsłużony wyjątek checked
Jeśli wywołujesz metodę z
throws OutOfStockExceptionbeztry/catchi bez własnegothrows, kompilator zgłaszaunreported exception OutOfStockException; must be caught or declared to be thrown.Zła kolejność bloków catch
Java wybiera pierwszy pasujący
catch. Jeślicatch (Exception e)stoi przedcatch (NumberFormatException e), drugi nigdy nie zadziała. Kompilator zgłaszaexception NumberFormatException has already been caught. Bardziej szczegółowy wyjątek powinien stać wyżej.Pusty blok catch
catch (Exception e) { }połyka każdy błąd, także taki, którego się nie spodziewałeś. Przechwytuj tylko ten wyjątek, którego oczekujesz, i reaguj na niego w widoczny sposób.Dzielenie przez 0
Przy
intwyrażenie10 / 0rzucaArithmeticException. Przydoublewyjątku nie ma:10.0 / 0dajeInfinity. Dlategodividew przykładzie samo to sprawdza i rzuca wyjątek.
Zadania z tego tematu
Przećwicz to, czego się nauczyłeś, od razu w przeglądarce. Testy natychmiast sprawdzają twoje rozwiązanie.
Powiązane artykuły
- Dziedziczenie i interfejsyDziedziczenie w Javie w prosty sposób: extends, super, @Override, klasy abstrakcyjne, interfejsy i Comparable z przykładami. Do tego typowe błędy.Czytaj artykuł
- Instrukcje warunkoweInstrukcje warunkowe w Javie: if, else if, switch oraz && i || prosto wyjaśnione. Z przykładami i typowymi błędami, które kosztują punkty na kolokwium.Czytaj artykuł
- Lambdy i strumienieLambdy i strumienie w Javie w prosty sposób: filter, map, reduce, Comparator i groupingBy z przykładami. Do tego typowe błędy z toList() i reversed().Czytaj artykuł