Własne wyjątki
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 60 z 87.
Wbudowane wyjątki Java obejmują wiele typowych scenariuszy błędów, ale czasami potrzebujesz wyjątków specyficznych dla domeny swojej aplikacji. Własne wyjątki pozwalają tworzyć znaczące typy błędów, które jasno informują o tym, co poszło nie tak.
Aby utworzyć własny wyjątek, po prostu rozszerz istniejącą klasę wyjątku. W przypadku wyjątku sprawdzanego rozszerz Exception:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}W przypadku niekontrolowanego wyjątku rozszerz RuntimeException:
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}Wywołanie super(message) przekazuje komunikat o błędzie do klasy nadrzędnej, dzięki czemu jest on dostępny za pośrednictwem getMessage(). Następnie możesz zgłosić i przechwycić własny wyjątek tak jak każdy inny:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low: " + balance);
}
balance -= amount;
}
// Użycie
try {
account.withdraw(1000);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}Niestandardowe wyjątki zwiększają czytelność kodu i pozwalają wywołującym obsługiwać poszczególne warunki błędów na różne sposoby. Są szczególnie przydatne podczas tworzenia interfejsów API lub bibliotek, w których ważne jest jasne komunikowanie błędów.
Wyzwanie
ŁatwyZbudujmy system rezerwacji biletów, który używa niestandardowych wyjątków do obsługi różnych sytuacji błędów! Utworzysz znaczące typy wyjątków, które jasno informują, co poszło nie tak podczas rezerwacji biletów.
Rozmieścisz swój kod w czterech plikach:
TicketSoldOutException.java: Utwórz niestandardowy wyjątek kontrolowany (rozszerzającyException), który będzie zgłaszany, gdy bilety nie będą już dostępne. Konstruktor wyjątku powinien przyjmować komunikat i przekazywać go do klasy nadrzędnej za pomocąsuper(message).InvalidSeatException.java: Utwórz niestandardowy wyjątek niekontrolowany (rozszerzającyRuntimeException), który będzie zgłaszany, gdy ktoś spróbuje zarezerwować miejsce o nieprawidłowym numerze. Ten wyjątek również powinien przyjmować komunikat i przekazywać go do klasy nadrzędnej.TicketBooth.java: Utwórz klasę, która zarządza sprzedażą biletów. Kasa powinna śledzić łączną liczbę dostępnych miejsc oraz najwyższy prawidłowy numer miejsca. Dodaj:Konstruktor, który przyjmuje łączną liczbę dostępnych miejsc.
Metodę
bookTicket(int seatNumber), która weryfikuje rezerwację. Jeśli nie ma już biletów (liczba dostępnych miejsc wynosi 0 lub mniej), zgłoś wyjątekTicketSoldOutExceptionz komunikatem"No tickets remaining". Jeśli numer miejsca jest mniejszy niż 1 lub większy niż łączna liczba miejsc, zgłoś wyjątekInvalidSeatExceptionz komunikatem"Seat [seatNumber] does not exist". W przeciwnym razie zmniejsz liczbę dostępnych miejsc o 1 i wypiszBooked seat [seatNumber] successfully.Metodę
getAvailableSeats(), która zwraca aktualną liczbę dostępnych miejsc.Main.java: Połącz wszystkie elementy systemu biletowego! Otrzymasz dwa dane wejściowe: łączną liczbę miejsc i numer miejsca do zarezerwowania.Utwórz obiekt
TicketBoothz podaną łączną liczbą miejsc. Następnie spróbuj zarezerwować wskazane miejsce wewnątrz bloku try-catch. PonieważTicketSoldOutExceptionjest wyjątkiem kontrolowanym, musisz go obsłużyć. Najpierw przechwyćTicketSoldOutExceptioni wypiszBooking failed: [exception message]. Następnie przechwyćInvalidSeatExceptioni wypisz tekst w tym samym formacie:Booking failed: [exception message].Po bloku try-catch wypisz
Remaining seats: [count], używając metody pobierającej.
Otrzymasz kolejno dwa dane wejściowe: łączną liczbę miejsc (liczba całkowita) i numer miejsca do zarezerwowania (liczba całkowita).
Zwróć uwagę, że wyjątki kontrolowane zmuszają wywołujący kod do ich obsługi (za pomocą try-catch lub throws), podczas gdy wyjątki niekontrolowane nie wymagają jawnej obsługi. Wybierz typ wyjątku w zależności od tego, czy wywołujący kod powinien przewidywać dany błąd i móc na niego zareagować!
Spróbuj swoich sił
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int totalSeats = scanner.nextInt();
int seatNumber = scanner.nextInt();
// TODO: Utwórz TicketBooth z podaną łączną liczbą miejsc
// TODO: Użyj bloku try-catch, aby spróbować zarezerwować miejsce
// - Najpierw przechwyć TicketSoldOutException i wypisz "Booking failed: [exception message]"
// - Przechwyć InvalidSeatException i wypisz "Booking failed: [exception message]"
// TODO: Po bloku try-catch wypisz "Remaining seats: [count]"
}
}
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