Poznaj tajniki najpopularniejszego języka programowania
w erze Internetu
Chyba wszyscy użytkownicy internetu spotkali się z Javą, często nawet o tym nie wiedząc. W ciągu ostatnich 10 lat zyskała ona ogromną popularność, szczególnie wśród programistów aplikacji sieciowych. Jednakże kojarzenie jej z językiem przeznaczonym wyłącznie do tworzenia takich programów jest dużym błędem. Java to w pełni funkcjonalny i doskonale dopracowany język programowania, nadający się do tworzenia różnych aplikacji, a nie tylko apletów działających na stronach internetowych.
W Javie pisane są gry sieciowe, systemy bankowości elektronicznej, pakiety wspomagające sprzedaż i obsługę klienta, a nawet aplikacje działające w telefonach komórkowych i komputerach przenośnych. Podstawową zaletą języka Java jest przenośność kodu -- raz napisany program można uruchomić na każdym urządzeniu, na którym zainstalowane jest odpowiednie środowisko uruchomieniowe, zwane JRE.
Książka "Praktyczny kurs Java" przeznaczona jest dla osób rozpoczynających swoją przygodę z programowaniem w tym języku. Opisuje podstawy języka, zasady programowania obiektowego i tworzenia własnych apletów i aplikacji. Czytając kolejne rozdziały, dowiesz się:
* Jakie typy danych wykorzystywane są w Javie
* Jak deklarować zmienne i wyprowadzać ich wartości na ekran
* W jaki sposób sterować przebiegiem wykonywania programu
* Jakie zasady rządzą programowaniem obiektowym
* Czym są klasy, obiekty, argumenty i metody
* Co to są wyjątki i jak je obsługiwać w programie
* Jak wykorzystać zaawansowane techniki programowania obiektowego w swoich aplikacjach
* W jaki sposób uzyskiwać dostęp do systemu plików z poziomu swojej aplikacji
* Jak tworzyć aplety i samodzielne aplikacje
Zapoznaj się z podstawami programowania w Javie i naucz się zasad programowania obiektowego, a także dowiedz się, czym są wyjątki w Javie i stwórz własne aplety i aplikacje.
1. IDZ DO
PRZYK£ADOWY ROZDZIA£
SPIS TRE CI Praktyczny kurs Java
Autor: Marcin Lis
KATALOG KSI¥¯EK ISBN: 83-7361-395-1
Format: B5, stron: 384
KATALOG ONLINE
ZAMÓW DRUKOWANY KATALOG
TWÓJ KOSZYK
Poznaj tajniki najpopularniejszego
DODAJ DO KOSZYKA jêzyka programowania w erze Internetu
Chyba wszyscy u¿ytkownicy internetu spotkali siê z Jav¹, czêsto nawet o tym nie
wiedz¹c. W ci¹gu ostatnich 10 lat zyska³a ona ogromn¹ popularno æ, szczególnie
CENNIK I INFORMACJE w ród programistów aplikacji sieciowych. Jednak¿e kojarzenie jej z jêzykiem
przeznaczonym wy³¹cznie do tworzenia takich programów jest du¿ym b³êdem.
ZAMÓW INFORMACJE Java to w pe³ni funkcjonalny i doskonale dopracowany jêzyk programowania,
O NOWO CIACH nadaj¹cy siê do tworzenia ró¿nych aplikacji, a nie tylko apletów dzia³aj¹cych
na stronach internetowych.
ZAMÓW CENNIK W Javie pisane s¹ gry sieciowe, systemy bankowo ci elektronicznej, pakiety
wspomagaj¹ce sprzeda¿ i obs³ugê klienta, a nawet aplikacje dzia³aj¹ce w telefonach
komórkowych i komputerach przeno nych. Podstawow¹ zalet¹ jêzyka Java jest
CZYTELNIA przeno no æ kodu -- raz napisany program mo¿na uruchomiæ na ka¿dym urz¹dzeniu,
na którym zainstalowane jest odpowiednie rodowisko uruchomieniowe, zwane JRE.
FRAGMENTY KSI¥¯EK ONLINE
Ksi¹¿ka „Praktyczny kurs Java” przeznaczona jest dla osób rozpoczynaj¹cych swoj¹
przygodê z programowaniem w tym jêzyku. Opisuje podstawy jêzyka, zasady
programowania obiektowego i tworzenia w³asnych apletów i aplikacji.
Czytaj¹c kolejne rozdzia³y, dowiesz siê:
• Jakie typy danych wykorzystywane s¹ w Javie
• Jak deklarowaæ zmienne i wyprowadzaæ ich warto ci na ekran
• W jaki sposób sterowaæ przebiegiem wykonywania programu
• Jakie zasady rz¹dz¹ programowaniem obiektowym
• Czym s¹ klasy, obiekty, argumenty i metody
• Co to s¹ wyj¹tki i jak je obs³ugiwaæ w programie
• Jak wykorzystaæ zaawansowane techniki programowania obiektowego
Wydawnictwo Helion
w swoich aplikacjach
ul. Chopina 6
• W jaki sposób uzyskiwaæ dostêp do systemu plików z poziomu swojej aplikacji
44-100 Gliwice
tel. (32)230-98-63 • Jak tworzyæ aplety i samodzielne aplikacje
e-mail: helion@helion.pl Zapoznaj siê z podstawami programowania w Javie i naucz siê zasad programowania
obiektowego, a tak¿e dowiedz siê, czym s¹ wyj¹tki w Javie i stwórz w³asne aplety
i aplikacje.
2. Spis treści
Wstęp ............................................................................................... 5
Rozdział 1. Podstawy .......................................................................................... 7
Lekcja 1. Struktura programu, kompilacja i wykonanie...............................................7
Lekcja 2. Podstawy obiektowości i typy danych ..........................................................9
Lekcja 3. Komentarze .................................................................................................12
Rozdział 2. Instrukcje języka ............................................................................. 17
Zmienne.............................................................................................................................17
Lekcja 4. Deklaracje i przypisania..............................................................................18
Lekcja 5. Wyprowadzanie danych na ekran ...............................................................21
Lekcja 6. Operacje na zmiennych...............................................................................27
Instrukcje sterujące............................................................................................................39
Lekcja 7. Instrukcja warunkowa if...else ....................................................................39
Lekcja 8. Instrukcja switch i operator warunkowy.....................................................45
Lekcja 9. Pętle.............................................................................................................49
Lekcja 10. Instrukcje break i continue........................................................................56
Tablice...............................................................................................................................63
Lekcja 11. Podstawowe operacje na tablicach............................................................64
Lekcja 12. Tablice wielowymiarowe..........................................................................68
Rozdział 3. Programowanie obiektowe ............................................................... 79
Podstawy ...........................................................................................................................79
Lekcja 13. Klasy, pola i metody .................................................................................80
Lekcja 14. Argumenty i przecią anie metod ..............................................................87
Lekcja 15. Konstruktory .............................................................................................98
Dziedziczenie ..................................................................................................................110
Lekcja 16. Klasy potomne ........................................................................................110
Lekcja 17. Specyfikatory dostępu i pakiety..............................................................118
Lekcja 18. Przesłanianie metod i składowe statyczne ..............................................132
Lekcja 19. Klasy i składowe i finalne.......................................................................145
Rozdział 4. Wyjątki ......................................................................................... 153
Lekcja 20. Blok try...catch ........................................................................................153
Lekcja 21. Wyjątki to obiekty...................................................................................162
Lekcja 22. Własne wyjątki........................................................................................169
3. 4 Praktyczny kurs Java
Rozdział 5. Programowanie obiektowe II .......................................................... 181
Polimorfizm.....................................................................................................................181
Lekcja 23. Konwersje typów i rzutowanie obiektów................................................181
Lekcja 24. Późne wiązanie i wywoływanie metod klas pochodnych .......................190
Lekcja 25. Konstruktory oraz klasy abstrakcyjne.....................................................199
Interfejsy..........................................................................................................................209
Lekcja 26. Tworzenie interfejsów.............................................................................209
Lekcja 27. Wiele interfejsów ....................................................................................216
Klasy wewnętrzne ...........................................................................................................226
Lekcja 28. Klasa w klasie .........................................................................................226
Lekcja 29. Rodzaje klas wewnętrznych i dziedziczenie ...........................................235
Lekcja 30. Klasy anonimowe i zagnie d one...........................................................244
Rozdział 6. System wejścia-wyjścia.................................................................. 253
Lekcja 31. Standardowe wejście...............................................................................253
Lekcja 32. Standardowe wejście i wyjście ...............................................................263
Lekcja 33. System plików.........................................................................................273
Lekcja 34. Operacje na plikach.................................................................................283
Rozdział 7. Aplikacje i aplety ........................................................................... 301
Aplety ..............................................................................................................................301
Lekcja 35. Podstawy apletów ...................................................................................301
Lekcja 36. Czcionki i kolory.....................................................................................310
Lekcja 37. Grafika ....................................................................................................319
Lekcja 38. Dźwięki i obsługa myszy ........................................................................330
Aplikacje .........................................................................................................................340
Lekcja 39. Tworzenie aplikacji.................................................................................340
Lekcja 40. Komponenty............................................................................................359
Skorowidz...................................................................................... 375
4. Rozdział 4.
Wyjątki
Praktycznie w ka dym większym programie powstają jakieś błędy. Powodów jest
bardzo wiele, mo e być to skutek niefrasobliwości programisty, zało enia, e wpro-
wadzone dane są zawsze poprawne, niedokładnej specyfikacji poszczególnych modu-
łów aplikacji, u ycia niesprawdzonych bibliotek czy nawet zwykłego zapomnienia
o zainicjowaniu jednej tylko zmiennej. Na szczęście w Javie, tak jak i w większości
współczesnych obiektowych języków programowania, istnieje mechanizm tzw. wyjąt-
ków, który pozwala na przechwytywanie błędów. Ta właśnie tematyka zostanie przed-
stawiona w kolejnych trzech lekcjach.
Lekcja 20. Blok try...catch
Lekcja 20. jest poświęcona wprowadzeniu w tematykę wyjątków. Zobaczymy, jakie
są sposoby zapobiegania powstawaniu niektórych typów błędów w programach,
dowiemy się, jak stosować przechwytujący błędy blok instrukcji VT[ECVEJ. Po-
znamy bli ej wyjątek o nieco egzotycznej dla początkujących programistów nazwie
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP, dzięki któremu będziemy mogli uniknąć błędów
związanych z przekroczeniem dopuszczalnego zakresu indeksów tablic.
Sprawdzanie poprawności danych
Powróćmy na chwilę do rozdziału 2. i lekcji 11. Znajdował się tam przykład, w którym
następowało odwołanie do nieistniejącego elementu tablicy (listing 2.38). Występowała
tam sekwencja instrukcji:
KPV VCD=? PGY KPV=?
VCD=?
Doświadczony programista od razu zauwa y, e instrukcje te są błędne, jako e zade-
klarowana została tablica dziesięcioelementowa, więc — poniewa indeksowanie
tablicy zaczyna się od zera — ostatni element tablicy ma indeks . Tak więc instrukcja
VCD=? powoduje próbę odwołania się do nieistniejącego jedenastego elementu
tablicy. Ten błąd jest jednak stosunkowo prosty do wychwycenia, nawet gdyby pomiędzy
deklaracją tablicy a nieprawidłowym odwołaniem były umieszczone inne instrukcje.
5. 154 Praktyczny kurs Java
Du o więcej kłopotów mogłyby nam sprawić sytuacja, gdyby np. tablica była deklaro-
wana w jednej klasie, a odwołanie do niej następowało w innej klasie. Taka przykładowa
sytuacja została przedstawiona na listingu 4.1.
Listing 4.1.
RWDNKE
ENCUU 6CDNKEC
]
RTKXCVG KPV=? VCDNKEC PGY KPV=?
RWDNKE KPV RQDKGT'NGOGPV
KPV KPFGMU
]
TGVWTP VCDNKEC=KPFGMU?
_
RWDNKE XQKF WUVCY'NGOGPV
KPV KPFGMU KPV YCTVQUE
]
VCDNKEC=KPFGMU? YCTVQUE
_
_
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
6CDNKEC VCDNKEC PGY 6CDNKEC
VCDNKECWUVCY'NGOGPV
KPV NKEDC VCDNKECRQDKGT'NGOGPV
5[UVGOQWVRTKPVNP
NKEDC
_
_
Powstały tu dwie klasy: 6CDNKEC oraz /CKP. W klasie 6CDNKEC zostało zadeklarowane
prywatne pole typu tablicowego o nazwie VCDNKEC, któremu została przypisana dzie-
sięcioelementowa tablica liczb całkowitych. Poniewa pole to jest polem prywatnym
(por. lekcja 17.), dostęp do niego mają jedynie inne składowe klasy 6CDNKEC. Dlatego
te powstały dwie metody RQDKGT'NGOGPV oraz WUVCY'NGOGPV operujące na elemen-
tach tablicy. Metoda RQDKGT'NGOGPV zwraca wartość zapisaną w komórce o indeksie
przekazanym jako argument, natomiast WUVCY'NGOGPV zapisuje wartość drugiego argu-
mentu w komórce o indeksie wskazywanym przez argument pierwszy.
W klasie /CKP tworzymy obiekt klasy 6CDNKEC i wykorzystujemy metodę WUVCY'NGOGPV
do zapisania w piątej komórce wartości . W kolejnej linii popełniamy drobny błąd.
W metodzie RQDKGT'NGOGPV odwołujemy się do nieistniejącego elementu o indeksie
. Musi to spowodować wystąpienie błędu w trakcie działania aplikacji (rysunek 4.1).
Błąd tego typu bardzo łatwo popełnić, gdy w klasie /CKP nie widzimy rozmiarów
tablicy, nietrudno więc o pomyłkę.
Rysunek 4.1.
Odwołanie
do nieistniejącego
elementu
w klasie Tablica
6. Rozdział 4. ♦ Wyjątki 155
Jak poradzić sobie z takim problemem? Pierwszym nasuwającym się sposobem jest
sprawdzanie w metodach RQDKGT'NGOGPV i WUVCY'NGOGPV, czy przekazane argumenty
nie przekraczają dopuszczalnych wartości. Jeśli takie przekroczenie wartości nastąpi,
nale y wtedy zasygnalizować błąd. To jednak prowokuje pytanie: w jaki sposób ten
błąd sygnalizować? Pomysłem znanym programistom C/C++ jest np. zwracanie przez
funkcję (metodę) wartości w przypadku błędu oraz wartości nieujemnej (najczę-
ściej zero), jeśli błąd nie wystąpił1. Ta metoda będzie dobra w przypadku metody
WUVCY'NGOGPV, która wyglądałaby wtedy następująco:
RWDNKE KPV WUVCY'NGOGPV
KPV KPFGMU KPV YCTVQUE
]
KH
KPFGMU VCDNKECNGPIVJ]
TGVWTP
_
GNUG]
VCDNKEC=KPFGMU? YCTVQUE
TGVWTP
_
_
Wystarczyłoby teraz w klasie /CKP testować wartość zwróconą przez WUVCY'NGOGPV,
aby sprawdzić, czy nie przekroczyliśmy dopuszczalnego indeksu tablicy. Niestety, tej
techniki nie mo na zastosować w przypadku metody RQDKGT'NGOGPV, przecie zwraca
ona wartość zapisaną w jednej z komórek tablicy. Czyli i u yte przed chwilą do
zasygnalizowania, czy operacja zakończyła się błędem, mogą być wartościami odczyta-
nymi z tablicy. Trzeba zatem wymyślić inny sposób. Mo e być to np. wykorzystanie
dodatkowego pola sygnalizującego w klasie 6CDNKEC. Pole to byłoby typu DQQNGCP.
Ustawione na VTWG oznaczałoby, e ostatnia operacja na klasie zakończyła się błędem,
natomiast ustawione na HCNUG, e ostatnia operacja zakończyła się sukcesem. Klasa
6CDNKEC miałaby wtedy postać, jak na listingu 4.2.
Listing 4.2.
RWDNKE
ENCUU 6CDNKEC
]
RTKXCVG KPV=? VCDNKEC PGY KPV=?
RWDNKE DQQNGCP Y[UVCRKN$NCF HCNUG
RWDNKE KPV RQDKGT'NGOGPV
KPV KPFGMU
]
KH
KPFGMU VCDNKECNGPIVJ]
Y[UVCRKN$NCF VTWG
TGVWTP
_
GNUG]
Y[UVCRKN$NCF HCNUG
TGVWTP VCDNKEC=KPFGMU?
_
_
1
To tylko przykład. Równie często stosuje się zwrócenie wartości zero jako oznaczenie prawidłowego
wykonania funkcji.
7. 156 Praktyczny kurs Java
RWDNKE XQKF WUVCY'NGOGPV
KPV KPFGMU KPV YCTVQUE
]
KH
KPFGMU VCDNKECNGPIVJ]
Y[UVCRKN$NCF VTWG
_
GNUG]
VCDNKEC=KPFGMU? YCTVQUE
Y[UVCRKN$NCF HCNUG
_
_
_
Do klasy dodaliśmy pole typu DQQNGCP o nazwie Y[UVCRKN$NCF. Jego początkowa
wartość to HCNUG. W metodzie RQDKGT'NGOGPV sprawdzamy najpierw, czy przekazany
indeks nie przekracza dopuszczalnej maksymalnej wartości. Jeśli tak, ustawiamy pole
Y[UVCRKN$NCF na VTWG oraz zwracamy wartość zero. Oczywiście, w tym przypadku
zwrócona wartość nie ma adnego praktycznego znaczenia (przecie wystąpił błąd),
niemniej coś musimy zwrócić. U ycie instrukcji TGVWTP i zwrócenie wartości typu KPV
jest bowiem konieczne, inaczej kompilator zgłosi błąd. Jeśli jednak argument przeka-
zany metodzie nie przekracza dopuszczalnego indeksu tablicy, pole Y[UVCRKN$NCF
ustawiamy na HCNUG oraz zwracamy wartość znajdującą się pod tym indeksem.
W metodzie WUVCY'NGOGPV postępujemy podobnie. Sprawdzamy, czy przekazany indeks
nie przekracza dopuszczalnej wartości. Jeśli tak, pole Y[UVCRKN$NCF ustawiamy na
VTWG, w przeciwnym przypadku dokonujemy przypisania wskazanej komórce tablicy
i ustawiamy Y[UVCRKN$NCF na HCNUG. Po takiej modyfikacji obu metod w klasie /CKP
mo emy ju bez problemów stwierdzić, czy operacje wykonywane na klasie 6CDNKEC
zakończyły się sukcesem. Przykładowe wykorzystanie mo liwości, jakie daje nowe
pole, zostało przedstawione na listingu 4.3.
Listing 4.3.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
6CDNKEC VCDNKEC PGY 6CDNKEC
VCDNKECWUVCY'NGOGPV
KPV NKEDC VCDNKECRQDKGT'NGOGPV
KH
VCDNKECY[UVCRKN$NCF]
5[UVGOQWVRTKPVNP
9[UVæRK D æF
_
GNUG]
5[UVGOQWVRTKPVNP
NKEDC
_
_
_
Podstawowe wykonywane operacje są takie same, jak w przypadku klasy z listingu 4.1.
Po pobraniu elementu sprawdzamy jednak, czy operacja ta zakończyła się sukcesem
i wyświetlamy odpowiedni komunikat na ekranie. Identyczne sprawdzenie mo na
8. Rozdział 4. ♦ Wyjątki 157
wykonać równie po wywołaniu metody WUVCY'NGOGPV. Wykonanie kodu z listingu 4.3
spowoduje rzecz jasna wyświetlenie napisu 9[UVæRK D æF (rysunek 4.2).
Rysunek 4.2.
Efekt wykonania
programu
z listingu 4.3
Sposobów poradzenia sobie z problemem przekroczenia indeksu tablicy mo na by
zapewne wymyślić jeszcze kilka. Metody tego typu mają jednak powa ną wadę:
programiści mają tendencję do ich… niestosowania. Często mo liwy błąd wydaje się
zbyt banalny, aby się nim zajmować, czasami po prostu się zapomina się o sprawdza-
niu pewnych warunków. Dodatkowo przedstawione wy ej sposoby, czyli zwracanie
wartości sygnalizacyjnej czy dodatkowe zmienne, powodują niepotrzebne rozbudo-
wywanie kodu aplikacji, co paradoksalnie mo e prowadzić do powstawania kolejnych
błędów, czyli błędów powstałych przez napisanie kodu zajmującego się obsługą błę-
dów… W Javie zastosowano więc mechanizm tak zwanych wyjątków, znany na pewno
programistom C++ i Object Pascala2.
Wyjątki w Javie
Wyjątek (ang. exception) jest to byt programistyczny, który powstaje w sytuacji wy-
stąpienia błędu. Z powstaniem wyjątku spotkaliśmy się ju w rozdziale 2. w lekcji 11.
Był to wyjątek spowodowany przekroczeniem dopuszczalnego zakresu tablicy. Po-
ka my go raz jeszcze. Na listingu 4.4 została zaprezentowana odpowiednio spreparo-
wana klasa /CKP.
Listing 4.4.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
KPV VCD=? PGY KPV=?
VCD=?
_
_
Deklarujemy tablicę liczb typu KPV o nazwie VCD oraz próbujemy przypisać elementowi
o indeksie (czyli wykraczającym poza zakres tablicy) wartość . Jeśli skompilu-
jemy i uruchomimy taki program, na ekranie zobaczymy obraz widoczny na rysunku 4.3.
Został tu wygenerowany wyjątek o nazwie #TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP, czyli
wyjątek oznaczający, e indeks tablicy znajduje się poza jej granicami.
2
Sama technika obsługi sytuacji wyjątkowych sięga jednak lat sześćdziesiątych ubiegłego stulecia
(czyli wieku XX).
9. 158 Praktyczny kurs Java
Rysunek 4.3.
Odwołanie
do nieistniejącego
elementu tablicy
spowodowało
wygenerowanie
wyjątku
Oczywiście, gdyby mo liwości wyjątków kończyłyby się na wyświetlaniu informacji
na ekranie i przerywaniu działania programu, ich przydatność byłaby mocno ograni-
czona. Na szczęście, wygenerowany wyjątek mo na przechwycić i wykonać własny kod
obsługi błędu. Do takiego przechwycenia słu y blok instrukcji VT[ECVEJ. W naj-
prostszej postaci wygląda on następująco:
VT[]
KPUVTWMELG OQIæEG URQYQFQYCè Y[LæVGM
_
ECVEJ
6[R9[LæVMW KFGPV[HKMCVQT9[LæVMW]
QDU WIC Y[LæVMW
_
W nawiasach klamrowych występujących po słowie VT[ umieszczamy instrukcję,
która mo e spowodować wystąpienie wyjątku. W bloku występującym po ECVEJ
umieszczamy kod, który ma zostać wykonany, kiedy wyjątek wystąpi. W przypadku
klasy /CKP z listingu 4.4 blok VT[ECVEJ nale ałoby zastosować sposób przedsta-
wiony na listingu 4.5.
Listing 4.5.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
KPV VCD=? PGY KPV=?
VT[]
VCD=?
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
0KGRTCYKF QY[ KPFGMU VCDNKE[
_
_
_
Jak widać, wszystko odbywa się tu zgodnie z wcześniejszym ogólnym opisem. W bloku
VT[ znalazła się instrukcja VCD=? , która — jak wiemy — spowoduje wygene-
rowanie wyjątku. W nawiasach okrągłych występujących po instrukcji ECVEJ został
wymieniony rodzaj wyjątku, który zostanie wygenerowany: #TTC[+PFGZ1WV1H$QWPFU
3
å'ZEGRVKQP, oraz jego identyfikator: G. Identyfikator to nazwa , która pozwala na
wykonywanie operacji związanych z wyjątkiem, czym jednak zajmiemy się w kolejnej
3
Dokładniej jest to nazwa zmiennej obiektowej, wyjaśnimy to bli ej w lekcji 21.
10. Rozdział 4. ♦ Wyjątki 159
lekcji. W bloku po ECVEJ znajduje się instrukcja 5[UVGOQWVRTKPVNP wyświetlająca
odpowiedni komunikat na ekranie. Tym razem po uruchomieniu kodu zobaczmy widok
zaprezentowany na rysunku 4.4.
Rysunek 4.4.
Wyjątek został
przechwycony
w bloku try…catch
Blok VT[ECVEJ nie musi jednak obejmować tylko jednej instrukcji ani te tylko in-
strukcji mogących wygenerować wyjątek. Przypomnijmy ponownie listing 2.38. Blok
VT[ mógłby w tym wypadku objąć wszystkie trzy instrukcje, czyli klasa /CKP miałaby
wtedy postać jak na listingu 4.6.
Listing 4.6.
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
VT[]
KPV VCD=? PGY KPV=?
VCD=?
5[UVGOQWVRTKPVNP
KGUKæV[ GNGOGPV VCDNKE[ OC YCTVQ è
VCD=?
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
0KGRTCYKF QY[ KPFGMU VCDNKE[
_
_
_
Nie istnieje równie konieczność obejmowania blokiem VT[ instrukcji bezpośrednio
generujących wyjątek, tak jak miało to miejsce w dotychczasowych przykładach. Wyjątek
wygenerowany przez obiekt klasy ; mo e być bowiem przechwytywany w klasie :,
która korzysta z obiektów klasy ;. Poka emy to na przykładzie klas z listingu 4.1.
Klasa 6CDNKEC pozostanie bez zmian, natomiast klasę /CKP zmodyfikujemy tak, aby
miała wygląd zaprezentowany na listingu 4.7.
Listing 4.7.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
6CDNKEC VCDNKEC PGY 6CDNKEC
VT[]
VCDNKECWUVCY'NGOGPV
KPV NKEDC VCDNKECRQDKGT'NGOGPV
5[UVGOQWVRTKPVNP
NKEDC
_
11. 160 Praktyczny kurs Java
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
0KGRTCYKF QY[ KPFGMU VCDNKE[
_
_
_
Spójrzmy, w bloku VT[ wykonujemy trzy instrukcje, z których jedna: KPV NKEDC
VCDNKECRQDKGT'NGOGPV
jest odpowiedzialna za wygenerowanie wyjątku. Wyją-
tek jest przecie jednak generowany w ciele metody RQDKGT'NGOGPV klasy 6CDNKEC, a nie
w klasie /CKP! Zostanie on jednak przekazany klasie /CKP, jako e wywołuje ona metodę
klasy 6CDNKEC. Tym samym w klasie /CKP mo emy zastosować blok VT[ECVEJ.
Z identyczną sytuacją będziemy mieli do czynienia w przypadku hierarchicznego
wywołania metod jednej klasy. Czyli w sytuacji, kiedy metoda H wywołuje metodę I,
która wywołuje metodę J, która z kolei generuje wyjątek. W ka dej z wymienionych
metod mo na zastosować blok VT[ECVEJ do przechwycenia tego wyjątku. Dokładnie
taki przykład jest widoczny na listingu 4.8.
Listing 4.8.
RWDNKE
ENCUU 'ZCORNG
]
RWDNKE XQKF H
]
VT[]
I
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC H
_
_
RWDNKE XQKF I
]
VT[]
J
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC I
_
_
RWDNKE XQKF J
]
KPV=? VCD PGY KPV=?
VT[]
VCD=?
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC J
_
_
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
'ZCORNG GZ PGY 'ZCORNG
12. Rozdział 4. ♦ Wyjątki 161
VT[]
GZH
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC OCKP
_
_
_
Taką klasę skompilujemy bez adnych problemów. Musimy jednak dobrze zdawać
sobie sprawę, jak taki kod będzie wykonywany. Pytanie bowiem brzmi: które bloki
VT[ zostaną wykonane? Zasada jest następująca: zostanie wykonany blok najbli szy
instrukcji powodującej wyjątek. Czyli w przypadku przedstawionym na listingu 4.8
jedynie blok obejmujący wywołanie metody VCD=? w metodzie J. Jeśli jednak
będziemy usuwać kolejne bloki VT[ najpierw z instrukcji J, następnie I, H i ostatecznie
z OCKP, zobaczymy, e faktycznie wykonywany jest zawsze blok najbli szy miejsca
wystąpienia błędu. Po usunięciu wszystkich instrukcji VT[ wyjątek nie zostanie obsłu-
ony w naszej klasie i obsłu y go maszyna wirtualna Javy, co zaowocuje znanym nam
ju komunikatem na konsoli. Zwróćmy jednak uwagę, e w tym wypadku zostanie wy-
świetlona cała hierarchia metod, w których był propagowany wyjątek (rysunek 4.5).
Rysunek 4.5.
Przy
hierarchicznym
wywołaniu metod
po wystąpieniu
wyjątku otrzymamy
ich nazwy
Ćwiczenia do samodzielnego wykonania
20.1. Popraw kod klasy z listingu 4.2 tak, aby w metodach RQDKGT'NGOGPV i WUVCY'NGOGPV
było równie sprawdzane, czy przekazany indeks nie przekracza minimalnej dopusz-
czalnej wartości.
20.2. Zmień kod klasy /CKP z listingu 4.3 w taki sposób, aby było równie sprawdzane,
czy wywołanie metody WUVCY'NGOGPV zakończyło się sukcesem.
20.3. Popraw kod z listingu 4.2 tak, aby do wychwytywania błędów był wykorzysty-
wany mechanizm wyjątków zamiast instrukcji warunkowej KH.
20.4. Napisz klasę 'ZCORNG, w której będzie się znajdowała metoda o nazwie C, która
z kolei będzie wywoływała metodę o nazwie D. W metodzie C wygeneruj wyjątek
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP. Napisz następnie klasę /CKP zawierającą metodę
OCKP, w której zostanie utworzony obiekt klasy 'ZCORNG i zostaną wywołane metody
C oraz D tego obiektu. W metodzie OCKP zastosuj bloki VT[ECVEJ, przechwytujące
powstały wyjątek.
13. 162 Praktyczny kurs Java
Lekcja 21. Wyjątki to obiekty
W lekcji 20. poznaliśmy wyjątek sygnalizujący przekroczenie dopuszczalnego zakresu
tablicy. To oczywiście nie jedyny dostępny wyjątek, czas poznać równie inne ich typy.
W lekcji 21. dowiemy się więc, e wyjątki są tak naprawdę obiektami, a tak e, e tworzą
one hierarchiczną strukturę. Poka emy, jak przechwytywać wiele wyjątków w jednym
bloku VT[ oraz udowodnimy, e bloki VT[ECVEJ mogą być zagnie d ane. Oka e się,
e jeden wyjątek ogólny mo e obsłu yć wiele błędnych sytuacji.
Dzielenie przez zero
Rodzajów wyjątków jest bardzo wiele. Wiemy ju , jak reagować na przekroczenie
zakresu tablicy. Poznajmy zatem inny typ wyjątku, powstający, kiedy zostanie podjęta
próba wykonania nielegalnego dzielenia przez zero. W tym celu musimy spreparować
odpowiedni fragment kodu. Wystarczy, e w metodzie OCKP umieścimy przykładową
instrukcję:
KPV NKEDC .
Kompilacja takiego kodu przebiegnie bez problemu, jednak próba wykonania musi
skończyć się komunikatem o błędzie, widocznym na rysunku 4.6. Widzimy wyraźnie,
e tym razem został zgłoszony wyjątek #TKVJOGVKE'ZEGRVKQP (wyjątek arytmetyczny).
Rysunek 4.6.
Próba wykonania
dzielenia przez zero
Wykorzystując wiedzę z lekcji 20., nie powinniśmy mieć adnych problemów z napi-
saniem kodu, który taki wyjątek przechwyci. Trzeba wykorzystać dobrze nam znaną
instrukcję VT[ECVEJ w postaci:
VT[]
KPV NKEDC
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
KPUVTWMELG FQ Y[MQPCPKC MKGF[ Y[UVæRK Y[LæVGM
_
Intuicja podpowiada nam ju zapewne, e rodzajów wyjątków mo e być bardzo, bardzo
du o. I faktycznie tak jest, w klasach dostarczonych w JDK (w wersji SE) jest ich
zdefiniowanych blisko 300. Aby sprawnie się nimi posługiwać, musimy dowiedzieć
się, czym tak naprawdę są wyjątki.
Wyjątek jest obiektem
Wyjątek, który określaliśmy jako byt programistyczny, to nic innego jak obiekt,
który powstaje, kiedy w programie wystąpi sytuacja wyjątkowa. Skoro wyjątek jest
14. Rozdział 4. ♦ Wyjątki 163
obiektem, to wspominany wcześniej typ wyjątku (#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP,
#TKVJOGVKE'ZEGRVKQP) to nic innego jak klasa opisująca ten e obiekt. Jeśli teraz spoj-
rzymy ponownie na ogólną postać instrukcji VT[ECVEJ:
VT[]
KPUVTWMELG OQIæEG URQYQFQYCè Y[LæVGM
_
ECVEJ
6[R9[LæVMW KFGPV[HKMCVQT9[LæVMW]
QDU WIC Y[LæVMW
_
jasnym stanie się, e w takim razie KFGPV[HKMCVQT9[LæVMW to zmienna obiektowa, wska-
zująca na obiekt wyjątku. Na tym obiekcie mo emy wykonywać operacje zdefiniowane
w klasie wyjątku. Mo emy np. uzyskać systemowy komunikat o błędzie. Wystarczy
wywołać metodę IGV/GUUCIG
. Zobaczmy to na przykładzie wyjątku generowanego
podczas próby wykonania dzielenia przez zero. Jest on zaprezentowany na listingu 4.9.
Listing 4.9.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
VT[]
KPV NKEDC
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[UVCRK Y[LæVGM CT[VOGV[EP[
5[UVGOQWVRTKPVNP
-QOWPKMCV U[UVGOQY[
5[UVGOQWVRTKPVNP
GIGV/GUUCIG
_
_
_
Wykonujemy tutaj próbę niedozwolonego dzielenia przez zero oraz przechwytujemy
wyjątek klasy #TKVJOGVKE'ZEGRVKQP. W bloku ECVEJ najpierw wyświetlamy nasze
własne komunikaty o błędzie, a następnie komunikat systemowy. Po uruchomieniu
kodu na ekranie zobaczymy widok zaprezentowany na rysunku 4.7.
Rysunek 4.7.
Wyświetlenie
systemowego
komunikatu obłędzie
Istnieje jeszcze jedna mo liwość uzyskania komunikatu o wyjątku, mianowicie umiesz-
czenie w argumencie instrukcji 5[UVGOQWVRTKPVNP zmiennej wskazującej na obiekt
wyjątku, czyli w przypadku listingu 4.9:
5[UVGOQWVRTKPVNP
G
15. 164 Praktyczny kurs Java
W pierwszej chwili mo e się to wydawać nieco dziwne, bo niby skąd instrukcja
5[UVGOQWVRTKPVNP ma wiedzieć, co w takiej sytuacji wyświetlić? Zauwa my jednak,
e jest to sytuacja analogiczna, jak w przypadku typów prostych (por. lekcja 5.). Skoro
udawało się automatycznie przekształcać np. zmienną typu KPV na ciąg znaków, uda
się równie przekształcić zmienną typu obiektowego. Bli ej tym problemem zajmiemy
się w rozdziale piątym.
Jeśli teraz z programie z listingu 4.9 zamienimy instrukcję:
5[UVGOQWVRTKPVNP
GIGV/GUUCIG
na:
5[UVGOQWVRTKPVNP
G
otrzymamy nieco dokładniejszy komunikat określający dodatkowo klasę wyjątku, tak
jak jest to widoczne na rysunku 4.8.
Rysunek 4.8.
Pełniejszy komunikat
o typie wyjątku
Hierarchia wyjątków
Ka dy wyjątek jest obiektem pewnej klasy. Klasy podlegają z kolei regułom dziedzi-
czenia, zgodnie z którymi powstaje hierarchia klas. Kiedy zatem pracujemy z wyjątkami,
musimy tę kwestię wziąć pod uwagę. Wszystkie standardowe wyjątki, które mo emy
przechwytywać w naszych aplikacjach za pomocą bloku VT[ECVEJ, dziedziczą z klasy
'ZEGRVKQP, która z kolei dziedziczy z 6JTQYCDNG oraz 1DLGEV. Hierarchia klas dla wyjątku
#TKVJOGVKE'ZEGRVKQP, który wykorzystywaliśmy we wcześniejszych przykładach, jest
zaprezentowana na rysunku 4.9.
Rysunek 4.9.
Hierarchia klas
dla wyjątku
ArithmeticException
Wynika z tego kilka własności. Przede wszystkim, jeśli spodziewamy się, e dana
instrukcja mo e wygenerować wyjątek typu :, mo emy zawsze przechwycić wyjątek
ogólniejszy, czyli wyjątek, którego typem będzie jedna z klas nadrzędnych do :. Jest
to bardzo wygodna technika. Przykładowo z klasy 4WPVKOG'ZEGRVKQP dziedziczy bar-
dzo wiele klas wyjątków odpowiadających najró niejszym błędom. Jedną z nich jest
#TKVJOGVKE'ZEGRVKQP. Jeśli instrukcje, które obejmujemy blokiem VT[ECVEJ, mogą
16. Rozdział 4. ♦ Wyjątki 165
spowodować wiele ró nych wyjątków, zamiast stosować wiele oddzielnych instrukcji
przechwytujących konkretne typy błędów, często lepiej jest zastosować jedną prze-
chwytującą wyjątek bardziej ogólny. Spójrzmy na listing 4.10.
Listing 4.10.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
VT[]
KPV NKEDC
_
ECVEJ
4WPVKOG'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[UVCRK Y[LæVGM ECUW Y[MQPCPKC
5[UVGOQWVRTKPVNP
-QOWPKMCV U[UVGOQY[
5[UVGOQWVRTKPVNP
G
_
_
_
Jest to znany nam ju program, generujący błąd polegający na próbie wykonania
niedozwolonego dzielenia przez zero. Tym razem jednak zamiast wyjątku klasy
#TKVJOGVKE'ZEGRVKQP przechwytujemy wyjątek klasy nadrzędnej 4WPVKOG'ZEGRVKQP.
Co więcej, nic nie stoi na przeszkodzie, aby przechwycić wyjątek jeszcze ogólniejszy,
czyli wyjątek klasy nadrzędnej do 4WPVKOG'ZEGRVKQP. Jak widać na rysunku 4.9, byłaby
to klasa 'ZEGRVKQP.
Przechwytywanie wielu wyjątków
W jednym bloku VT[ECVEJ mo na przechwytywać wiele wyjątków. Konstrukcja
taka zawiera wtedy jeden blok VT[ i wiele bloków ECVEJ. Schematycznie wygląda ona
następująco:
VT[]
KPUVTWMELG OQIæEG URQYQFQYCè Y[LæVGM
_
ECVEJ
-NCUC9[LæVMW KFGPV[HKMCVQT9[LæVMW]
QDU WIC Y[LæVMW
_
ECVEJ
-NCUC9[LæVMW KFGPV[HKMCVQT9[LæVMW]
QDU WIC Y[LæVMW
_
18. ECVEJ
-NCUC9[LæVMW P KFGPV[HKMCVQT9[LæVMWP]
QDU WIC Y[LæVMW P
_
Po wygenerowaniu wyjątku jest sprawdzane, czy jest on klasy -NCUC9[LCVMW, jeśli tak
— są wykonywane instrukcje obsługi tego wyjątku i blok VT[ECVEJ jest opuszczany.
Je eli jednak wyjątek nie jest klasy -NCUC9[LCVMW, jest sprawdzane, czy jest on klasy
-NCUC9[LæVMW itd.
19. 166 Praktyczny kurs Java
Przy tego typu konstrukcjach nale y jednak pamiętać o hierarchii wyjątków, nie jest
bowiem obojętne, w jakiej kolejności będą one przechwytywane. Ogólna zasada jest
taka, e nie ma znaczenia kolejność, o ile wszystkie wyjątki są na jednym poziomie
hierarchii. Jeśli jednak przechwytujemy wyjątki z ró nych poziomów, najpierw muszą
to być wyjątki bardziej szczegółowe, czyli stojące ni ej w hierarchii, a dopiero po nich
wyjątki bardziej ogólne, czyli stojące wy ej w hierarchii.
Nie mo na zatem najpierw przechwycić wyjątku 4WPVKOG'ZEGRVKQP, a dopiero nim
wyjątku #TKVJOGVKE'ZEGRVKQP (por. rysunek 4.9), gdy skończy się to błędem kompi-
lacji. Jeśli więc dokonamy próby kompilacji przykładowego programu przedstawionego
na listingu 4.11, efektem będą komunikaty widoczne na rysunku 4.10.
Listing 4.11.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
VT[]
KPV NKEDC
_
ECVEJ
4WPVKOG'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
G
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
G
_
_
_
Rysunek 4.10.
Błędna hierarchia
wyjątków powoduje
błąd kompilacji
Dzieje się tak dlatego, e (mo na powiedzieć) błąd bardziej ogólny zawiera ju
w sobie błąd bardziej szczegółowy. Jeśli zatem przechwytujemy najpierw wyjątek
4WPVKOG'ZEGRVKQP, to tak jak byśmy przechwycili ju wyjątki wszystkich klas dziedzi-
czących z 4WPVKOG'ZEGRVKQP. Dlatego te kompilator protestuje.
Kiedy jednak mo e przydać się sytuacja, e najpierw przechwytujemy wyjątek szcze-
gółowy, a potem dopiero ogólny? Otó , wtedy, kiedy chcemy w specyficzny sposób
zareagować na konkretny typ wyjątku, a wszystkie pozostałe z danego poziomu hie-
rarchii obsłu yć w identyczny, standardowy sposób. Taka przykładowa sytuacja jest
przedstawiona na listingu 4.12.
20. Rozdział 4. ♦ Wyjątki 167
Listing 4.12.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
2WPMV RWPMV PWNN
KPV NKEDC
VT[]
NKEDC
RWPMVZ NKEDC
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
0KGRTCYKF QYC QRGTCELC CT[VOGV[EPC
5[UVGOQWVRTKPVNP
G
_
ECVEJ
'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
$ æF QIÎNP[
5[UVGOQWVRTKPVNP
G
_
_
_
Zostały zadeklarowane dwie zmienne: pierwsza typu 2WPMV o nazwie RWPMV oraz druga
typu KPV o nazwie NKEDC. Zmiennej RWPMV została przypisana wartość pusta PWNN, nie
został zatem utworzony aden obiekt klasy 2WPMV. W bloku VT[ są wykonywane dwie
błędne instrukcje. Pierwsza z nich to znane nam z poprzednich przykładów dzielenie
przez zero. Druga instrukcja z bloku VT[ to z kolei próba odwołania się do pola Z nie-
istniejącego obiektu klasy 2WPMV (przecie zmienna RWPMV zawiera wartość PWNN). Ponie-
wa chcemy w sposób niestandardowy zareagować na błąd arytmetyczny, najpierw
przechwytujemy błąd typu #TKVJOGVKE'ZEGRVKQP i, w przypadku kiedy wystąpi, wyświe-
tlamy na ekranie napis 0KGRTCYKF QYC QRGTCELC CT[VOGV[EPC. W drugim bloku ECVEJ
przechwytujemy wszystkie inne mo liwe wyjątki, w tym tak e wyjątek 0WNN2QKPVGT
å'ZEGRVKQP występujący, kiedy próbujemy wykonać operacje na zmiennej obiektowej,
która zawiera wartość PWNN.
Po uruchomieniu kodu z listingu 4.12 na ekranie pojawi się zgłoszenie tylko pierwszego
błędu. Dzieje się tak dlatego, e po jego wystąpieniu blok VT[ został przerwany, a ste-
rowanie zostało przekazane blokowi ECVEJ. Czyli jeśli w bloku VT[ któraś z instrukcji
spowoduje wygenerowanie wyjątku, dalsze instrukcje z bloku VT[ nie zostaną wykonane.
Nie miała więc szansy zostać wykonana nieprawidłowa instrukcja RWPMVZ NKEDC.
Jeśli jednak usuniemy wcześniejsze dzielenie przez zero, przekonamy się, e i ten błąd
zostanie przechwycony przez drugi blok ECVEJ, a na ekranie pojawi się stosowny komu-
nikat (rysunek 4.11).
Rysunek 4.11.
Odwołanie do pustej
zmiennej obiektowej
zostało wychwycone
przez drugi blok catch
21. 168 Praktyczny kurs Java
Zagnieżdżanie bloków try...catch
Bloki VT[ECVEJ mo na zagnie d ać. To znaczy, e w jednym bloku przechwytują-
cym wyjątek : mo e istnieć drugi blok, który będzie przechwytywał wyjątek ;. Sche-
matycznie taka konstrukcja wygląda następująco:
VT[]
KPUVTWMELG OQIæEG URQYQFQYCè Y[LæVGM
VT[]
KPUVTWMELG OQIæEG URQYQFQYCè Y[LæVGM
_
ECVEJ
6[R9[LæVMW KFGPV[HKMCVQT9[LæVMW]
QDU WIC Y[LæVMW
_
_
ECVEJ
6[R9[LæVMW KFGPV[HKMCVQT9[LæVMW]
QDU WIC Y[LæVMW
_
Zagnie d enie takie mo e być wielopoziomowe, czyli w ju zagnie d onym bloku
VT[ mo na umieścić kolejny blok VT[, choć w praktyce takich piętrowych konstrukcji
zazwyczaj się nie stosuje. Zwykle nie ma takiej potrzeby. Maksymalny poziom takiego
bezpośredniego zagnie d enia z reguły nie przekracza dwóch poziomów. Aby na prak-
tycznym przykładzie pokazać taką dwupoziomową konstrukcję, zmodyfikujemy przy-
kład z listingu 4.12. Zamiast obejmowania jednym blokiem VT[ dwóch instrukcji powo-
dujących błąd, zastosujemy zagnie d enie, tak jak jest to widoczne na listingu 4.13.
Listing 4.13.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
2WPMV RWPMV PWNN
KPV NKEDC
VT[]
VT[]
NKEDC
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
0KGRTCYKF QYC QRGTCELC CT[VOGV[EPC
5[UVGOQWVRTKPVNP
2T[RKUWLú OKGPPGLNKEDC YCTVQ è
NKEDC
_
RWPMVZ NKEDC
_
ECVEJ
'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
$ æF QIÎNP[
5[UVGOQWVRTKPVNP
G
_
_
_
22. Rozdział 4. ♦ Wyjątki 169
Podobnie jak w poprzednim przypadku, deklarujemy dwie zmienne: RWPMV klasy 2WPMV
oraz NKEDC typu KPV. Zmiennej RWPMV przypisujemy wartość pustą PWNN. W wewnętrznym
bloku VT[ próbujemy wykonać nieprawidłowe dzielenie przez zero i przechwytujemy
wyjątek #TKVJOGVKE'ZEGRVKQP. Jeśli on wystąpi, zmienna NKEDC otrzymuje domyślną
wartość równą , dzięki czemu mo na wykonać kolejną operację, czyli próbę przypi-
sania polu Z obiektu RWPMV wartości zmiennej NKEDC. Rzecz jasna, przypisanie takie
nie mo e zostać wykonane, gdy zmienna RWPMV jest pusta, jest zatem generowany
wyjątek 0WNN2QKPVGT'ZEGRVKQP, który jest przechwytywany przez zewnętrzny blok VT[.
Widać więc, e zagnie d anie bloków VT[ mo e być przydatne, choć warto zauwa yć,
e identyczny efekt mo na osiągnąć, korzystając równie z niezagnie d onej postaci
instrukcji VT[ECVEJ (por. ćwiczenie 21.3).
Ćwiczenia do samodzielnego wykonania
21.1. Popraw kod z listingu 4.11 tak, aby przechwytywanie wyjątków odbywało się
w prawidłowej kolejności.
21.2. Zmodyfikuj kod z listingu 4.12 tak, aby zostały zgłoszone oba typy błędów:
#TKVJOGVKE'ZEGRVKQP oraz 0WNN2QKPVGT'ZEGRVKQP.
21.3. Zmodyfikuj kod z listingu 4.5 w taki sposób, aby usunąć zagnie d enie bloków
VT[ECVEJ, nie zmieniając jednak efektów działania programu.
Lekcja 22. Własne wyjątki
Wyjątki mo emy przechwytywać, aby zapobiec niekontrolowanemu zakończeniu
programu w przypadku wystąpienia błędu. Tą technikę poznaliśmy w lekcjach 20. i 21.
Okazuje się jednak, e mo na je równie samemu zgłaszać, a tak e e mo na tworzyć
nowe, nieistniejące wcześniej klasy wyjątków. Tej właśnie tematyce jest poświęcona
bie ąca, 22., lekcja.
Zgłoś wyjątek
Wiemy, e wyjątki są obiektami. Skoro tak, zgłoszenie własnego wyjątku będzie po-
legało po prostu na utworzeniu nowego obiektu klasy opisującej wyjątek. Dokładniej za
pomocą instrukcji PGY nale y utworzyć nowy obiekt klasy, która pośrednio lub bezpo-
średnio dziedziczy z klasy 6JTQYCDNG. W najbardziej ogólnym przypadku będzie to klasa
'ZEGRVKQP. Tak utworzony obiekt musi stać się parametrem instrukcji VJTQY. Jeśli zatem
gdziekolwiek w pisanym przez nas kodzie chcemy zgłosić wyjątek ogólny, wystarczy,
e napiszemy:
VJTQY PGY 'ZEGRVKQP
W specyfikacji metody musimy jednak zaznaczyć, e będziemy w niej zgłaszać wyjątek
danej klasy. Robimy to za pomocą instrukcji VJTQYU, w ogólnej postaci:
URGE[HKMCVQTAFQUVGRW =UVCVKE? =HKPCN? V[RAYCTCECP[ PCYCAOGVQF[
CTIWOGPV[
VJTQYU -NCUC9[LæVMW -NCUC9[LæVMW -NCUC9[LCVMWP
]
VTG è OGVQF[
_
23. 170 Praktyczny kurs Java
Zobaczmy, jak to wygląda w praktyce. Załó my, e mamy klasę /CKP, a w niej metodę
OCKP. Jedynym zadaniem tej metody będzie zgłoszenie wyjątku klasy 'ZEGRVKQP. Klasa
taka jest widoczna na listingu 4.14.
Listing 4.14.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
VJTQYU 'ZEGRVKQP
]
VJTQY PGY 'ZEGRVKQP
_
_
W deklaracji metody OCKP zaznaczyliśmy, e mo e ona generować wyjątek klasy
'ZEGRVKQP poprzez u ycie instrukcji VJTQYU 'ZEGRVKQP. W ciele metody OCKP została
natomiast wykorzystana instrukcja VJTQY, która jako parametr otrzymała nowy obiekt
klasy 'ZEGRVKQP. Po uruchomieniu takiego programu na ekranie zobaczymy widok
zaprezentowany na rysunku 4.12. Jest to najlepszy dowód, e faktycznie udało nam
się zgłosić wyjątek.
Rysunek 4.12.
Zgłoszenie wyjątku
klasy Exception
Utworzenie obiektu wyjątku nie musi mieć miejsca bezpośrednio w instrukcji VJTQY,
mo na utworzyć go wcześniej, przypisać zmiennej obiektowej i dopiero tę zmienną
wykorzystać jako parametr dla VJTQY. Czyli zamiast pisać:
VJTQY PGY 'ZEGRVKQP
mo emy równie dobrze zastosować konstrukcję:
'ZEGRVKQP GZEGRVKQP PGY 'ZEGRVKQP
VJTQY GZEGRVKQP
W obu przedstawionych przypadkach efekt będzie identyczny, najczęściej korzystamy
jednak z pierwszego zaprezentowanego sposobu.
Jeśli chcemy, aby zgłaszany wyjątek otrzymał komunikat, nale y przekazać go jako
parametr konstruktora klasy 'ZEGRVKQP, czyli napiszemy wtedy:
VJTQY PGY 'ZEGRVKQP
MQOWPKMCV
lub:
'ZEGRVKQP GZEGRVKQP PGY 'ZEGRVKQP
MQOWPKMCV
VJTQY GZEGRVKQP
24. Rozdział 4. ♦ Wyjątki 171
Oczywiście, mo na tworzyć obiekty wyjątków klas dziedziczących z 'ZEGRVKQP.
Przykładowo: jeśli sami wykryjemy próbę dzielenia przez zero, być mo e zechcemy
wygenerować nasz wyjątek, nie czekając, a zgłosi go maszyna wirtualna. Spójrzmy
na listing 4.15.
Listing 4.15.
RWDNKE
ENCUU 'ZCORNG
]
RWDNKE FQWDNG H
KPV NKEDC KPV NKEDC
]
KH
NKEDC
VJTQY PGY #TKVJOGVKE'ZEGRVKQP
KGNGPKG RTG GTQ
NKEDC
NKEDC
TGVWTP NKEDC NKEDC
_
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
'ZCORNG GZCORNG PGY 'ZCORNG
KPV Y[PKM GZCORNGH
5[UVGOQWVRTKPVNP
9[PKM RKGTYUGIQ FKGNGPKC
Y[PKM
Y[PKM GZCORNGH
5[UVGOQWVRTKPVNP
9[PKM FTWIKGIQ FKGNGPKC
Y[PKM
_
_
W klasie 'ZCORNG jest zdefiniowana metoda H, która przyjmuje dwa argumenty typu KPV.
Ma ona zwracać wynik dzielenia wartości przekazanej w argumencie NKEDC przez
wartość przekazaną w argumencie NKEDC. Jest zatem jasne, e NKEDC nie mo e mieć
wartości zero. Sprawdzamy to, wykorzystując instrukcję warunkową KH. Jeśli oka e
się, e NKEDC ma jednak wartość zero, za pomocą instrukcji VJTQY wyrzucamy nowy
wyjątek klasy #TKVJOGVKE'ZEGRVKQP. W konstruktorze klasy przekazujemy komunikat
informujący o dzieleniu przez zero. Podajemy w nim wartości argumentów metody H,
tak by łatwo mo na było stwierdzić, jakie parametry spowodowały błąd.
W celu przetestowania działania metody H w klasie 'ZCORNG pojawiła się równie metoda
OCKP. Tworzymy w niej nowy obiekt klasy 'ZCORNG i przypisujemy go zmiennej o nazwie
GZCORNG. Następnie dwukrotnie wywołujemy metodę H, raz przekazując jej argumenty
równe i , drugi raz przekazując jej argumenty równe i . Spodziewamy się, e
w drugim przypadku program zgłosi wyjątek #TKVJOGVKE'ZEGRVKQP ze zdefiniowanym
przez nas komunikatem. Faktycznie program zachowa się w taki właśnie sposób, co
jest widoczne na rysunku 4.13.
Rysunek 4.13.
Zgłoszenie
własnego
wyjątku klasy
ArithmeticException
25. 172 Praktyczny kurs Java
Ponowne zgłoszenie przechwyconego wyjątku
Wiemy ju , jak przechwytywać wyjątki oraz jak samemu zgłaszać wystąpienie wyjątku.
To pozwoli nam zapoznać się z techniką ponownego zgłaszania (potocznie: wyrzuca-
nia) ju przechwyconego wyjątku. Jak pamiętamy, bloki VT[ECVEJ mo na zagnie -
d ać bezpośrednio, a tak e stosować je w przypadku kaskadowo wywoływanych metod.
Jeśli jednak na którymkolwiek poziomie przechwytywaliśmy wyjątek, jego obsługa
ulegała zakończeniu. Nie zawsze jest to korzystne zachowanie, czasami istnieje potrzeba,
aby po wykonaniu naszego bloku obsługi wyjątek nie był niszczony, ale przekazywany
dalej. Aby osiągnąć takie zachowanie, musimy zastosować instrukcję VJTQY. Schema-
tycznie wyglądałoby to następująco:
VT[]
KPUVTWMELG OQIæEG URQYQFQYCè Y[LæVGM
_
ECVEJ
V[R6[LæVMW KFGPV[HKMCVQT9[LæVMW]
KPUVTWMELG QDU WIWLæEG U[VWCELú Y[LæVMQYæ
VJTQY KPFGV[HKMCVQT9[LæVMW
_
Listing 4.16 przedstawia, jak taka sytuacja wygląda w praktyce. W bloku VT[ jest
wykonywana niedozwolona instrukcja dzielenia przez zero. W bloku ECVEJ najpierw
wyświetlamy na ekranie informację o przechwyceniu wyjątku, a następnie za pomocą
instrukcji VJTQY ponownie wyrzucamy (zgłaszamy) przechwycony ju wyjątek. Poniewa
w programie nie ma ju innego bloku VT[ECVEJ, który mógłby przechwycić ten
wyjątek, zostanie on obsłu ony standardowo przez maszynę wirtualną. Dlatego te na
ekranie zobaczymy widok zaprezentowany na rysunku 4.14.
Listing 4.16.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
VT[]
KPV NKEDC
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
6W Y[LæVGM QUVC RTGEJY[EQP[
VJTQY G
_
_
_
Rysunek 4.14.
Ponowne zgłoszenie
raz przechwyconego
wyjątku
26. Rozdział 4. ♦ Wyjątki 173
W przypadku zagnie d onych bloków VT[ sytuacja wygląda analogicznie. Wyjątek
przechwycony w bloku wewnętrznym i ponownie zgłoszony mo e być obsłu ony
w bloku zewnętrznym, w którym mo e być oczywiście zgłoszony kolejny raz itd. Jest
to zobrazowane na listingu 4.17.
Listing 4.17.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
VW FQYQNPG KPUVTWMELG
VT[]
VW FQYQNPG KPUVTWMELG
VT[]
KPV NKEDC
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
6W Y[LæVGM QUVC RTGEJY[EQP[ RKGTYU[
TC
VJTQY G
_
_
ECVEJ
#TKVJOGVKE'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
6W Y[LæVGM QUVC RTGEJY[EQP[ FTWIK TC
VJTQY G
_
_
_
Mamy tu dwa zagnie d one bloki VT[. W bloku wewnętrznym zostaje wykonana nie-
prawidłowa instrukcja dzielenia przez zero. Zostaje ona w tym bloku przechwycona,
a na ekranie zostaje wyświetlony komunikat o pierwszym przechwyceniu wyjątku.
Następnie wyjątek jest ponownie zgłaszany. W bloku zewnętrznym następuje drugie
przechwycenie, wyświetlenie drugiego komunikatu oraz kolejne zgłoszenie wyjątku.
Poniewa nie istnieje trzeci blok VT[ECVEJ, ostatecznie wyjątek jest obsługiwany
przez maszynę wirtualną. Po uruchomieniu zobaczymy widok zaprezentowany na
rysunku 4.15.
Rysunek 4.15.
Przechwytywanie
i ponowne zgłaszanie
wyjątków
W identyczny sposób będą zachowywały się wyjątki w przypadku kaskadowego wywo-
ływania metod. Z sytuacją tego typu mieliśmy do czynienia w przypadku przykładu
z listingu 4.8. W klasie 'ZCORNG były wtedy zadeklarowane cztery metody: OCKP, H, I, J.
Metoda OCKP wywoływała metodę H, ta z kolei metodę I, a metoda I metodę J. W ka dej
27. 174 Praktyczny kurs Java
z metod znajdował się blok VT[ECVEJ, jednak zawsze działał tylko ten najbli szy
miejsca wystąpienia wyjątku (por. lekcja 20.). Zmodyfikujemy więc kod z listingu 4.8
tak, aby za ka dym razem wyjątek był po przechwyceniu ponownie zgłaszany. Kod
realizujący to zadanie jest przedstawiony na listingu 4.18.
Listing 4.18.
RWDNKE
ENCUU 'ZCORNG
]
RWDNKE XQKF H
]
VT[]
I
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC H
VJTQY G
_
_
RWDNKE XQKF I
]
VT[]
J
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC I
VJTQY G
_
_
RWDNKE XQKF J
]
KPV=? VCD PGY KPV=?
VT[]
VCD=?
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC J
VJTQY G
_
_
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
'ZCORNG GZ PGY 'ZCORNG
VT[]
GZH
_
ECVEJ
#TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
9[LæVGM OGVQFC OCKP
VJTQY G
_
_
_
28. Rozdział 4. ♦ Wyjątki 175
Wszystkie wywołania metod pozostały niezmienione, w ka dym bloku ECVEJ została
natomiast dodana instrukcja VJTQY ponownie zgłaszająca przechwycony wyjątek. Ry-
sunek 4.16 pokazuje efekty uruchomienia przedstawionego kodu. Widać wyraźnie, jak
wyjątek jest propagowany po wszystkich metodach, począwszy od metody J a skoń-
czywszy na metodzie OCKP. Poniewa w bloku VT[ECVEJ metody OCKP jest on ponow-
nie zgłaszany, na ekranie jest tak e widoczna reakcja maszyny wirtualnej.
Rysunek 4.16.
Kaskadowe
przechwytywanie
wyjątków
Tworzenie własnych wyjątków
Programując w Javie, nie musimy zdawać się na wyjątki systemowe, które dostajemy
wraz z JDK. Nic nie stoi na przeszkodzie, aby tworzyć własne klasy wyjątków. Wystar-
czy więc, e napiszemy klasę pochodną pośrednio lub bezpośrednio z klasy 6JTQYCDNG,
a będziemy mogli wykorzystywać ją do zgłaszania naszych własnych wyjątków. W prak-
tyce jednak wyjątki wyprowadzamy z klasy 'ZEGRVKQP i klas od niej pochodnych. Klasa
taka w najprostszej postaci będzie miała postać:
RWDNKE
ENCUU PCYCAMNCU[ GZVGPFU 'ZEGRVKQP
]
VTG è MNCU[
_
Przykładowo mo emy utworzyć bardzo prostą klasę o nazwie )GPGTCN'ZEGRVKQP
(wyjątek ogólny) w postaci:
RWDNKE
ENCUU )GPGTCN'ZEGRVKQP GZVGPFU 'ZEGRVKQP
]
_
To w zupełności wystarczy. Nie musimy dodawać adnych nowych pól i metod. Ta
klasa jest pełnoprawną klasą obsługującą wyjątki, z której mo emy korzystać w taki
sam sposób, jak ze wszystkich innych klas opisujących wyjątki. Na listingu 4.19 jest
widoczna przykładowa klasa OCKP, która generuje wyjątek )GPGTCN'ZEGRVKQP.
Listing 4.19.
RWDNKE
ENCUU /CKP
]
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
VJTQYU )GPGTCN'ZEGRVKQP
29. 176 Praktyczny kurs Java
]
VJTQY PGY )GPGTCN'ZEGRVKQP
_
_
W metodzie OCKP za pomocą instrukcji VJTQYU zaznaczamy, e metoda ta mo e zgłaszać
wyjątek klasy )GPGTCN'ZEGRVKQP, sam wyjątek zgłaszamy natomiast przez zastosowanie
instrukcji VJTQY, dokładnie w taki sam sposób, jak we wcześniejszych przykładach.
Na rysunku 4.17 jest widoczny efekt działania takiego programu, faktycznie zgłoszony
został wyjątek nowej klasy: )GPGTCN'ZEGRVKQP.
Rysunek 4.17.
Zgłaszanie własnych
wyjątków
Własne klasy wyjątków mo na wyprowadzać równie z klas pochodnych od 'ZEGRVKQP.
Moglibyśmy np. rozszerzyć klasę #TKVJOGVKE'ZEGRVKQP o wyjątek zgłaszany wyłącznie
wtedy, kiedy wykryjemy dzielenie przez zero. Klasę taką nazwalibyśmy KXKFG$[GTQ
å'ZEGRVKQP. Miałaby ona postać widoczną na listingu 4.20.
Listing 4.20.
RWDNKE
ENCUU KXKFG$[GTQ'ZEGRVKQP GZVGPFU #TKVJOGVKE'ZEGRVKQP
]
_
Mo emy teraz zmodyfikować program z listingu 4.15 tak, aby po wykryciu dzielenia
przez zero był zgłaszany wyjątek naszego nowego typu, czyli KXKFG$[GTQ'ZEGRVKQP.
Klasa taka została przedstawiona na listingu 4.21.
Listing 4.21.
RWDNKE
ENCUU 'ZCORNG
]
RWDNKE FQWDNG H
KPV NKEDC KPV NKEDC
]
KH
NKEDC
VJTQY PGY KXKFG$[GTQ'ZEGRVKQP
TGVWTP NKEDC NKEDC
_
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
'ZCORNG GZCORNG PGY 'ZCORNG
FQWDNG Y[PKM GZCORNGH
5[UVGOQWVRTKPVNP
9[PKM RKGTYUGIQ FKGNGPKC
Y[PKM
30. Rozdział 4. ♦ Wyjątki 177
Y[PKM GZCORNGH
5[UVGOQWVRTKPVNP
9[PKM FTWIKGIQ FKGNGPKC
Y[PKM
_
_
W stosunku do kodu z listingu 4.15 zmiany nie są du e, ograniczają się do zmiany typu
zgłaszanego wyjątku w metodzie H. Zadaniem tej metody nadal jest zwrócenie wyniku
dzielenia argumentu NKEDC przez argument NKEDC. W metodzie OCKP dwukrotnie
wywołujemy metodę H, pierwszy raz z prawidłowymi danymi i drugi raz z danymi,
które spowodują wygenerowanie wyjątku. Efekt działania przedstawionego kodu jest
widoczny na rysunku 4.18.
Rysunek 4.18.
Zgłoszenie wyjątku
DivideByZeroException
Zwróćmy jednak uwagę, e pierwotnie (listing 4.15) przy zgłaszaniu wyjątku para-
metrem konstruktora był komunikat (czyli wartość typu 5VTKPI). Tym razem nie mo-
gliśmy jej umieścić, gdy nasza klasa KXKFG$[GTQ'ZEGRVKQP nie posiada konstruktora
przyjmującego jako parametr obiektu typu 5VTKPI, a jedynie bezparametrowy kon-
struktor domyślny. Aby zatem mo na było przekazywać nasze własne komunikaty,
nale y dopisać do klasy KXKFG$[GTQ'ZEGRVKQP odpowiedni konstruktor. Przyjmie ona
wtedy postać widoczną na listingu 4.22.
Listing 4.22.
RWDNKE
ENCUU KXKFG$[GTQ'ZEGRVKQP GZVGPFU #TKVJOGVKE'ZEGRVKQP
]
RWDNKE KXKFG$[GTQ'ZEGRVKQP
5VTKPI UVT
]
UWRGT
UVT
_
_
Teraz instrukcja VJTQY z listingu 4.21 mogłaby przyjąć np. następującą postać:
VJTQY PGY KXKFG$[GTQ'ZEGRVKQP
KGNGPKG RTG GTQ
NKEDC
NKEDC
Sekcja finally
Do bloku VT[ mo emy dołączyć sekcję HKPCNN[, która będzie wykonana zawsze, nie-
zale nie od tego, co będzie działo się w bloku VT[. Schematycznie taka konstrukcja
będzie wyglądała następująco:
31. 178 Praktyczny kurs Java
VT[]
KPUVTWMELG OQIæEG URQYQFQYCè Y[LæVGM
_
ECVEJ
]
KPUVTWMELG UGMELK ECVEJ
_
HKPCNN[]
KPUVTWMELG UGMELK HKPCNN[
_
Zgodnie z tym, co zostało napisane wcześniej, instrukcje sekcji HKPCNN[ są wykonywane
zawsze, niezale nie od tego, czy w bloku VT[ wystąpi wyjątek, czy nie. Obrazuje to
przykład z listingu 4.23, który jest oparty na kodzie z listingów 4.20 i 4.21.
Listing 4.23.
RWDNKE
ENCUU 'ZCORNG
]
RWDNKE FQWDNG H
KPV NKEDC KPV NKEDC
]
KH
NKEDC
VJTQY PGY KXKFG$[GTQ'ZEGRVKQP
KGNGPKG RTG GTQ
NKEDC
NKEDC
TGVWTP NKEDC NKEDC
_
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
'ZCORNG GZCORNG PGY 'ZCORNG
FQWDNG Y[PKM
VT[]
Y[PKM GZCORNGH
_
ECVEJ
KXKFG$[GTQ'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
2TGEJY[EGPKG Y[LæVMW
_
HKPCNN[]
5[UVGOQWVRTKPVNP
5GMELC HKPCNN[
_
VT[]
Y[PKM GZCORNGH
_
ECVEJ
KXKFG$[GTQ'ZEGRVKQP G]
5[UVGOQWVRTKPVNP
2TGEJY[EGPKG Y[LæVMW
_
HKPCNN[]
5[UVGOQWVRTKPVNP
5GMELC HKPCNN[
_
_
_
Jest to znana nam klasa 'ZCORNG z metodą H wykonującą dzielenie przekazanych jej
argumentów. Tym razem metoda H pozostała bez zmian w stosunku do wersji z listingu
4.21, czyli zgłasza błąd KXKFG$[GTQ'ZEGRVKQP. Zmodyfikowaliśmy natomiast metodę
32. Rozdział 4. ♦ Wyjątki 179
OCKP. Oba wywołania metody zostały ujęte w bloki VT[ECVEJHKPCNN[. Pierwsze
wywołanie nie powoduje powstania wyjątku, nie jest więc wykonywany pierwszy blok
ECVEJ, jest natomiast wykonywany pierwszy blok HKPCNN[. Tym samym na ekranie
pojawi się napis 5GMELC HKPCNN[ .
Drugie wywołanie metody H powoduje wygenerowanie wyjątku, zostaną zatem wyko-
nane zarówno instrukcje bloku ECVEJ, jak i instrukcje bloku HKPCNN[. Na ekranie pojawią
się zatem dwa napisy: 2TGEJY[EGPKG Y[LæVMW oraz 5GMELC HKPCNN[ . Ostatecznie
wyniki działania całego programu będzie taki, jak ten zaprezentowany na rysunku 4.19.
Rysunek 4.19.
Blok finally jest
wykonywany
niezale nie od tego,
czy pojawi się wyjątek
Sekcję HKPCNN[ mo na zastosować równie w przypadku instrukcji, które nie powodują
wygenerowania wyjątku. Stosujemy wtedy instrukcję VT[HKPCNN[ w postaci:
VT[]
KPUVTWMELG
_
HKPCNN[]
KPUVTWMELG
_
Działanie jest takie samo jak w przypadku bloku VT[ECVEJHKPCNN[, to znaczy
kod z bloku HKPCNN[ zostanie wykonany zawsze, niezale nie od tego, jakie instrukcje
znajdą się w bloku VT[. Przykładowo: nawet jeśli w bloku VT[ znajdzie się instrukcja
TGVWTP lub zostanie wygenerowany wyjątek, blok HKPCNN[ i tak zostanie wykonany.
Obrazuje to przykład zaprezentowany na listingu 4.24.
Listing 4.24.
RWDNKE
ENCUU 'ZCORNG
]
RWDNKE KPV H
]
VT[]
TGVWTP
_
HKPCNN[]
5[UVGOQWVRTKPVNP
5GMELC HKPCNN[ H
_
_
RWDNKE XQKF H
]
VT[]
KPV NKEDC
_
33. 180 Praktyczny kurs Java
HKPCNN[]
5[UVGOQWVRTKPVNP
5GMELC HKPCNN[ H
_
_
RWDNKE UVCVKE XQKF OCKP
5VTKPI CTIU=?
]
'ZCORNG GZCORNG PGY 'ZCORNG
GZCORNGH
GZCORNGH
_
_
Ćwiczenia do samodzielnego wykonania
22.1. Napisz klasę 'ZCORNG, w której zostaną zadeklarowane metody H i OCKP. W meto-
dzie H napisz dowolną instrukcję generującą wyjątek 0WNN2QKPVGT'ZEGRVKQP. W metodzie
OCKP wywołaj metodę H, przechwyć wyjątek za pomocą bloku VT[ECVEJ.
22.2. Zmodyfikuj kod z listingu 4.17 tak, aby generowany, przechwytywany i ponownie
zgłaszany był wyjątek #TTC[+PFGZ1WV1H$QWPFU'ZEGRVKQP.
22.3. Napisz klasę o takim układzie metod, jak w przypadku klasy 'ZCORNG z listingu
4.18. W najbardziej zagnie d onej metodzie J wygeneruj wyjątek #TKVJOGVKE'ZEGRVKQP.
Przechwyć ten wyjątek w metodzie I i zgłoś wyjątek klasy nadrzędnej do #TKVJOGVKE
å'ZEGRVKQP, czyli 4WPVKOG'ZEGRVKQP. Wyjątek ten przechwyć w metodzie H i zgłoś
wyjątek nadrzędny do 4WPVKOG'ZEGRVKQP, czyli 'ZEGRVKQP. Ten ostatni wyjątek prze-
chwyć w klasie OCKP.
22.4. Napisz klasę wyjątku o nazwie 0GICVKXG8CNWG'ZEGRVKQP oraz klasę 'ZCORNG, która
będzie z niego korzystać. W klasie 'ZCORNG napisz metodę o nazwie H, przyjmującą dwa
argumenty typu KPV. Metoda H powinna zwracać wartość będącą wynikiem odejmo-
wania argumentu pierwszego od argumentu drugiego. W przypadku jednak, gdyby
wynik ten był ujemny, powinien zostać zgłoszony wyjątek 0GICVKXG8CNWG'ZEGRVKQP.
Dopisz metodę OCKP, która przetestuje działanie metody H.