Wyjątki, rzutowanie typów, operator instanceOf

advertisement
Wyjątki,
rzutowanie typów,
operator instanceOf
Małgorzata Tomczyk
referat z JTP
prowadzący: mgr inż. Dominik Radziszowski
Wyjątki
Błędy w programach
Kiedy piszemy program nie zawsze możemy być
stuprocentowo pewni, że podczas jego wykonywania nie
wystąpią jakieś nieoczekiwane błędy, jak na przykład
odwołanie się do nieistniejącego pliku lub dzielenie przez 0.
Aby ustrzec nasz program przed możliwymi błędami często
jesteśmy zmuszeni dodać do niego mnóstwo instrukcji
warunkowych i wartowników, co zazwyczaj zmniejsza
czytelność kodu.
Czy zatem istnieje jakaś rozsądna alternatywa?
Wyjątki
Java posiada zapożyczony z języka Ada mechanizm
informowania o błędach: wyjątki (ang. exceptions).
Mechanizm obsługi wyjątków w Javie umożliwia
zaprogramowanie "wyjścia" z takich sytuacji krytycznych,
dzięki czemu program nie zawiesi się po wystąpieniu błędu
wykonując ciąg operacji obsługujących wyjątek
Rodzaje wyjątków
W Javie wyróżniamy dwa rodzaje wyjątków:
•wyjątki kontrolowane (ang. checked exeptions)–
stanowią większość wyjątków w Javie. Znaczy to, że
kompilator jest w stanie sprawić, że każda metoda zgłasza
tylko te wyjątki, które są jawnie wymienione w jej
deklaracji.
•wyjątki niekontrolowane (ang. unchecked exeptions) –
standardowe wyjątki i błędy zgłaszane przez system
wykonawczy, które są podklasami klas RuntimeExeption i
Error.
Klasa Throwable
Wszystkie wyjątki, jakie mogą wystąpić w programie muszą być
podklasą klasy Throwable. Poniższy rysunek pokazuje hierarchię
dziedziczenia klasy Throwable i jej najważniejszych podklas.
Użyteczne metody klasy Throwable
•String getMessage() - zwraca napis podany kontruktorowi
wyjątku Exception
•String toString() - zwraca napis reprezentujący nazwę wyjątku
(klasy wyjątku)
•void printStackTrace() - wypisuje call stack trace czyli
sekwencję metod, która została wywołana do momentu
wyrzucenia wyjątku
Więcej informacji:
http://java.sun.com/j2se/1.3/docs/api/java/lang/Throwable.html
Klasa Error
Wyjątki typu Error występują wtedy, gdy wystąpi sytuacja
specjalna w maszynie wirtualnej (np. błąd podczas linkowania).
Wyjątki tego typu nie powinny być obsługiwane w "zwykłych"
programach Javy.
Więcej informacji:
http://java.sun.com/j2se/1.3/docs/api/java/lang/Error.html
Klasa Exception
W większości programów generowane są i obsługiwane obiekty,
które dziedziczą z klasy Exception. Wyjątek tego typu oznacza,
że w programie wystąpił błąd, lecz nie jest to poważny błąd
systemowy.
Więcej informacji:
http://java.sun.com/j2se/1.3/docs/api/java/lang/Exception.html
Klasa RuntimeException
Szczególną podklasę klasy Exception stanowią wyjątki, które
występują podczas wykonywania programu, są to wyjątki typu
RunTimeExceptions (i jej podklas np.: NullPointerException,
ClassCastException, IllegalThreadStateException i
ArrayOutOfBoundsException) i występują np.: wtedy, gdy
zostaną wyczerpane zasoby systemowe, nastąpi odwołanie do
nie istniejącego elementu tablicy i inne.
Więcej informacji:
http://java.sun.com/j2se/1.3/docs/api/java/lang/RuntimeExcept
ion.html
Deklarowanie typów wyjątków
Czasami do opisu sytuacji wyjątkowych wygodnie jest mieć
więcej danych niż tylko napis, który udostępnia klasa
Exception. W takich wypadkach możemy utworzyć podklasy
klasy Exception, które będą zawierały dodatkowe dane (zwykle
ustawione przez konstruktor).
Przykład: Załóżmy, że chcemy zgłosić wyjątek
StudentNieZdalEgzaminu. Zgłaszany wyjątek powinien
zawierać informacje który student nie zdał egzaminu i z
czego.
public class StudentNieZdalEgzaminu extends Exeption{
public Student student;
public String przedmiot;
StudentNieZdalEgzaminu(Student nieszczesny, String
przedm){
super("Student " + nieszczesny.nazwisko+ "nie zdal
" + przedm);
student=nieszczesny;
przedmiot=przedm;
}
}
Instrukcja throw i klauzula throws
instrukcja throw – służy do zgłaszania wyjątków. Wymaga
podania obiektu reprezentującego wątek.
klauzula throws - w tej klauzuli podaje się wyjątki
kontrolowane przez daną metodę jako listę nazw
oddzielonych przecinkami
nazwaMetody(zmienne) throws Wyjatek1, Wyjatek2
{
instrukcje;
...
throw Wyjatek1;
...
}
Przykład użycia instrukcji throw i klauzuli throws
public void przeprowadzEgzamin(Student student, String
przedmiot) throws StudentNieZdalEgzaminu
{
if(student.ocena==2) throw
StudentNieZdalEgzaminu(student, przedmiot);
else student.wpiszDoIndexu(przedmiot, student.ocena);
}
Blok try oraz klauzule catch i finally
Wyjątki można wychwytywać za pomocą bloków try.
Składnia bloku try jest następująca:
try
blok
catch(typ_wyjatku id)
blok
catch(typ_wyjatku id)
blok
...
finally
blok
Treść instrukcji try jest wykonywana do chwili zgłoszenia wyjątku
lub do szczęśliwego jej zakończenia. Jeśli zostaje zgłoszony
wyjątek, to kolejne klauzule catch są przeszukiwane w celu
znalezienia takiej, która wymienia klasę zgłoszonego wyjątku, bądź
którąś z jej nadklas. Jeżeli klauzuli nie uda się znaleźć, to wyjątek
jest propagowany na zewnątrz instrukcji try do otaczających
instrukcji try, w których może być obsłużony. Instrukcja try może
zawierać dowolną liczbę klauzul catch (np. ani jednej). Wyjątek,
który nie został wychwycony jest, jest zgłaszany w miejscu
wywołania danej metody.
Jeżeli instrukcja try zawiera klauzulę finally to jest ona wykonywana
po wszystkich czynnościach związanych z obsługą klauzul catch.
Jest ona wykonywana zawsze bez względu na to, czy w bloku try
zostały zgłoszone jakieś wyjątki, czy też nie i czy zostały one
obsłużone.
Przykład użycia bloku try oraz klauzul catch i finally
try{
przeprowadzEgzamin(gotom,JTP);
}
catch(StudentNieZdalEgzaminu e){
System.out.println("Trudno, może następnym razem");
}
finally{
System.out.println("Dziękuję, panie doktorze, do
widzenia!");
}
Kiedy używać wyjątków
Wybór sytuacji, w których należy zgłosić wyjątek, nie
podgala żadnym sztywnym regułom. Należy jednak
pamiętać o tym, aby nie nadużywać wyjątków jako metody
zgłaszania sytuacji normalnych i oczekiwanych.
Konwersje typów
Konwersje typów
Java jest językiem ze ścisłą kontrolą typów, to znaczy, że w czasie
kompilacji jest wykonywana kontrola zgodności typów dla niemal
wszystkich wyrażeń. Java nie pozawala na przypisania wartości
niewłaściwego typu przez odrzucenie wszystkich potencjalnie
niepoprawnych fragmentów programów i wymaga użycia
operatorów konwersji typu w tych przypadkach, gdy zgodność
typów można sprawdzić tylko w czasie wykonywania programu.
W Javie posługujemy się dwoma rodzajami konwersji typów:
1. Konwersją niejawną
2. Konwersją jawną
Konwersje niejawne
Konwersje niejawne, to takie, które odbywają się automatycznie,
bez konieczności ingerencji programisty. Są dwa rodzaje
konwersji niejawnych:
1. Konwersja typów prostych – każdą wartość liczbową można
przypisać zmiennej, której typ obejmuje szerszy zakres
wartości.
2. Konwersja wartości całkowitoliczbowych na
zmiennopozycyjne – nie wiąże się ze stratą zakresu. Konwersja
niejawna w drugą stronę jest niemożliwa
Konwersje jawne
Gdy wartość jednego typu nie może być bezpośrednio
przypisana zmiennej innego typu, zachodzi często
możliwość użycia jawnej konwersji typów (rzutowania).
Operator konwersji powoduje utworzenie wartości
nowego typu stanowiącej jak najdokładniejszą
reprezentację wartości starego typu.
Konwersje jawne różnych typów
•boolean na int – niedozwolona
•double na long – część ułamkowa odrzucana przez
zaokrąglenie w kierunku 0
•double na float – może spowodować utratę dokładności
•typy całkowitoliczbowe – konwersja przez obcięcie
najstarszych bitów. Może spowodować b. dużą zmianę
wartości
•char na czałkowitoliczbową – przez wypełnienie starszych
16 bitów zerami
•całkowitoliczbowa na char – używa się najmniej
znaczących 16 bitów, pozostałe - ignorowane
Konwersje jawne referencji
Jawne konwersje mogą być również stosowane w przypadku
referencji. O ile obiekt podtypu może być użyty wszędzie tam,
gdzie obiekt jego nadtypu, o tyle przeciwne stwierdzenie nie jest
zwykle prawdziwe.
Możliwe są dwie konwersje referencji
1. konwersja w dół (zwężanie typu) – rzutowanie
nadtypu na podtyp – nie zawsze poprawna
2. konwersja w górę (rozszeżenie typu) – rzutowanie
podtypu na nadtyp – zawsze poprawna
Wyjątek ClassCastExeption
Dla przykładu załóżmy, że mamy trzy klasy: klasę Coffee i
dziedziczące po niej klasy: Mocca i Latte.
Jeżeli zatem dokonamy konwersji:
Mocca fancy=(Mocca)joe;
to nie będzie ona zawsze poprawna, ponieważ joe
niekoniecznie wskazuje na obiekt typu Mocca. Jeżeli tak
nie jest zgłoszony zostanie wyjątek ClassCastExeption.
Aby uniknąć kłopotów moglibyśmy go wyłapać i
obsłużyć, ale takie rozwiązanie uznawane jest za
nieeleganckie
Instrukcja instanceOf
Aby uniknąć rozwiązania tej sytuacji przez wyjątki możemy
użyć instrukcji instanceOf. Wywołanie
objekt instanceOf Klasa
zwraca wartość true jeżeli konwersja „obiekt” do klasy (albo
interface’u) „Klasa” udałaby się.
Przy pomocy tej instrukcji można przykładową konwersję
przeprowadzić tak:
if(joe instatceOf Mocca)
Mocca fancy = (Mocca)joe;
Bibliografia
•
Ken Arnold, James Gosling „Java TM”, WNT, Warszawa ’99
•
http://www.javasoft.pl/java/
•
http://www.weia.po.opole.pl/kaeii/
•
http://java.sun.com/j2se/1.3/docs/api/
Download