31 lipca 2008

SCJP - Popularne typy wyjątków

W ostatnim artykule – "SCJP – Wyjątki" – przedstawiłem temat wyjątków w języku Java. Zapowiedziałem w nim także, że konkretne typy wyjątków omówię w kolejnym artykule i to właśnie robie dzisiaj. Będzie więc o popularnych typach wyjątków, przy czym popularne to te, których znajomość wymagana jest na egzaminie SCJP.

Bodaj najpopularniejszym wyjątkiem jest ‘NullPointerException’. Dziedziczy on bezpośrednio z klasy ‘RuntimeException’ a więc jest wyjątkiem niekontrolowanym (ang. unchecked). Wyjątek ten rzucany jest przez Wirtualną Maszynę Javy (ang. akr. JVM) przy próbie odwołania się do obiektu (np. uruchomienie metody) z użyciem referencji, która ma wartość ‘null’.

Pamięć operacyjna wykonującego się programu składa się z dwóch obszarów: stosu (ang. stack) i sterty (ang. heap). Na stercie znajdują się obiekty, a na stosie kontekst wykonywanego kodu, tj. zmienne lokalne. Gdy wywołujemy metodę, to jej zmienne lokalne, a więc i przekazywane parametry zapisywane są na stosie. Pamięć ta zwalniana jest dopiero po zakończeniu wykonania metody. A co jeśli metody nigdy się nie kończą, za to wywołują (rekurencyjnie) kolejne metody? Wtedy właśnie, po pewnym czasie wyczerpuje się pamięć stosu i Wirtualna Maszyna Javy rzuca wyjątek ‘StackOverflowError’. Wyjątek ten jest podklasą (nie bezpośrednią) klasy ‘Error’ a więc jest to również wyjątek niekontrolowany. Zresztą, wszystkie opisywane tu wyjątki są wyjątkami niekontrolowanymi, a więc podklasami klasy ‘Error’ albo ‘RuntimeException’.

W artykule "SCJP - Klasy opakowujące typów prostych" pisałem między innymi o metodach konwersji z typu napisowego ‘String’ na typy numeryczne. Jedną z nich jest metoda ‘parseInt(…)’ z klasy ‘Integer’. Jeśli napis nie może być przekonwertowany na liczbę, tj. jest to np. "sto jeden", a nie "101", to metody te rzucają wyjątek ‘NumberFormatException’. Wyjątek ten jest podklasą klasy ‘IllegalArgumentException’. Zauważmy tutaj, jak hierarchia dziedziczenia klas wyjątków odzwierciedla hierarchię rodzajów błędów. Wyjątek ‘IllegalArgumentException’ oznacza, że argument metody jest z pewnych powodów nieprawidłowy, a jej podklasa ‘NumberFormatException’ precyzuje, że argument jest nieprawidłowy, bo nie może być przekonwertowany do wartości liczbowej.

Wyjątek ‘ArrayIndexOutOfBoundsException’ rzucany jest, gdy nastąpi odwołanie do indeksu tablicy, który jest z poza dopuszczalnego zakresu – tj. jeśli indeks jest liczbą ujemną lub większą bądź równą (numerujemy od zera) od ilości elementów w tablicy.

Wyjątek ‘ClassCastException’ jest efektem próby rzutowania obiektu na typ z nim nie kompatybilny.

Wyjątek ‘IllegalStateException’ oznacza, że stan urządzeń bądź zewnętrznych systemów, których nasz program używa jest nieprawidłowy i wykonywana operacja nie może być z tego powodu zakończona.

Wyjątek ‘AssertionError’ informuje, że nie jest prawdziwa jedna z asercji. Asercje będą tematem następnego artykułu, tak więc do tego tematu jeszcze powrócimy.

Wyjątek ‘ExceptionInInitializerError’ jest rzucany, gdy wystąpi błąd w trakcie statycznej inicjalizacji zmiennej, bądź w trakcie wykonania bloku inicjalizacyjnego.

Wyjątek ‘NoClassDefFoundError’ jest rzucany, gdy Wirtualna Maszyna Javy – a mówiąc precyzyjniej, mechanizm ładowania klas – nie może znaleźć odpowiedniej klasy. Przeważnie błąd ten spowodowany jest brakiem odpowiedniej biblioteki na ścieżce przeszukiwania (ang. classpath).

5 komentarzy:

Unknown pisze...

Dzieki ci Mariusz za twój cykl artykułów przygotowujących do SCJP!!
Korzystam z książki przygotowujacej do SCJP i twoje artykuły są dla mnie doskonałym uzupełnieniem rozdziałów.
Mam tylko nadzieje ze nie zaprzestałeś "blogowania" ani tym bardziej przygotowań do SCJP. TAK TRZYMAJ!
Życzę tobie (i sobie) zdania egzaminu na conajmniej 95% :)

Mariusz Lipiński pisze...

Dzięki za słowa zachęty:) Co do zmniejszonej aktywności na Blogu... no cóż, sezon urlopowy. W każdym razie przygotowania do SCJP będą kontynuowane. BTW - czemu artykuły czytasz "oprócz", a nie "zamiast" Książki? Zbyt lakoniczne?

Pozdr. Mariusz

Kazik Pogoda pisze...

"Wyjątek ‘NoClassDefFoundError’ jest rzucany, gdy Wirtualna Maszyna Javy – a mówiąc precyzyjniej, mechanizm ładowania klas – nie może znaleźć odpowiedniej klasy."

Nie jest to informacja ścisła. Powyższy opis pasuje do 'ClassNotFoundException'. ‘NoClassDefFoundError’ jest często rzucany właśnie wtedy, kiedy mechanizm ładowania klas doskonale znajduje daną klasę (jest obecna w classpath), natomiast z jakiegoś powodu nie można załadować definicji tej klasy. Jedną z przyczyn może tu być np. statyczne pole tej klasy o typie nieobecnym w classloader.

Mariusz Lipiński pisze...

Dzięki za "zasianie" wątpliwości :) Poczytałem trochę na Googlach na ten temat... dokształciłem się. Wszystkim zainteresowanym polecam lekturę dyskusji http://forums.sun.com/thread.jspa?threadID=743580&messageID=4259890

Szczególnie zasługuje na uwagę stwierdzenie "ClassNotFoundException is thrown if you directly use
a class which can't be found." oraz "NoClassDefFoundError is thrown if you directly use a
class which directly or indirectly uses another class
which can't be found."

Tak czy inaczej - mechanizm ładowania klas nie może znaleźć odpowiedniej klasy.

Unknown pisze...

Mariusz napisał:
> BTW - czemu artykuły czytasz "oprócz",
> a nie "zamiast" Książki? Zbyt lakoniczne?

hehe :) to przez te zapierające dech w piersi opisy przyrody :P