• Nie Znaleziono Wyników

Obsługa wyjątków

N/A
N/A
Protected

Academic year: 2021

Share "Obsługa wyjątków"

Copied!
44
0
0

Pełen tekst

(1)

Wykład 8:

(2)

Wyjątki

Wyjątek to sytuacja nienormalna, która pojawia się w trakcie wykonania programu.

W językach bez obsługi wyjątków, błędy są wykrywane i obsługiwane ręcznie, zwykle przez kody błędów.

Java dostarcza specjalnych konstrukcji językowych do sygnalizacji, wykrywania i obsługi błędów.

(3)

Wyjątki w Javie

Wyjątek to obiekt, który opisuje sytuację wyjątkową (błędną) powstałą w kodzie programu:

● Kiedy powstaje błąd, wyjątek opisujący go jest

"wyrzucany" w metodzie która ten błąd spowodowała.

● Metoda może "wyłapać" i "obsłużyć" wyjątek

samodzielnie, lub przekazać go dalej.

(4)

Konstrukcje Obsługi Wyjątków

● try – otacza część programu, którą chcemy

monitorować na wypadek sygnalizacji błędów

● catch – w parze z try, wyłapuje określone wyjątki i

obsługuje je w pewien sposób

● throw – sygnalizuje powstanie określonego wyjątku ● throws – określenie jakie wyjątki może dana metoda

sygnalizować

● finally – kod, który musi być koniecznie wywołany

(5)

Blok Obsługi Wyjątków

Blok try/catch/finally do obsługi dwóch rodzajów

wyjątków (TypWyjatku1 i TypWyjatku2): try {

//monitorowana część kodu } catch(TypWyjatku1 e) {

//obsluga wyjatku dla typu 1 } catch(TypWyjatku2 e) {

//obsluga wyjatku dla typu 2 } finally {

//kod do wykonanie przed zakonczeniem }

(6)

Hierarchia Wyjątków

● Throwable – obejmuje wszystkie wyjątki

● Exception – wyjątki do wyłapania przez

programy użytkowe

● RuntimeException – definiowane

automatycznie dla programów:

● dzielenie przez zero ● indeksowanie tablic ● itp.

● TypWyjatku – wyjątki użytkownika

● Error – nie do wyłapania przez programy

(7)

Domyślna Obsługa Wyjątków

class Wyjatek0 {

public static void main(String args[]) { int d = 0;

int a = 42 / d; }

}

Gdy system wykrywa dzielenie przez zero, tworzy nowy obiekt wyjątku, i wyrzuca go.

Z braku własnej procedury obsługi, wyjątek jest przechwycony przez procedurę domyślną, która wyświetla komunikat, stos wywołań i powoduje zakończenie.

(8)

Domyślna Obsługa Wyjątków

Stos wywołań: ciąg wywołań metod które prowadziły do wystąpienia błędu.

class Wyjatek1 {

static void metoda() { int d = 0;

int a = 10 / d; }

public static void main(String args[]) { Wyjatek1.metoda();

} }

(9)

Własna Obsługa Wyjątków

Korzyści własnej obsługi błędów: umożliwia poprawianie błędów, zapobiega zakończeniu działania programu.

class Wyjatek2 {

public static void main(String args[]) { int d, a;

Należy umieścić kod do monitorowania w bloku try:

try {

d = 0;

a = 42 / d;

System.out.println("Nieosiągalne"); }

(10)

Własna Obsługa Wyjątków

Należy określić które wyjątki chcemy wyłapać:

catch (ArithmeticException e) {

Oraz jak te wyjątki obsłużyć:

System.out.println("Dzielenie przez 0"); }

Kod po obsłudze wyjątku:

System.out.println("Po wyjatku"); }

(11)

Try i Catch

Bloki try i catch stanowią parę.

Gdy wyrzucany jest wyjątek w bloku try:

try {

d = 0;

a = 42 / d;

System.out.println("Nieosiągalne");

kontrola przechodzi natychmiast do bloku catch:

} catch (ArithmeticException e) { ... }

catch nie może wyłapać wyjątków z innych bloków try,

(12)

Maskowanie Błędów

Wyjątek jest obsługiwany, potem program kontynuuje tak jakby nic się nie wydarzyło.

Generowanie liczb losowych:

import java.util.Random; class ObslugaBledow {

public static void main(String args[]) { int a = 0, b = 0, c = 0;

(13)

Maskowanie Błędów

Obsługa błędu gdy jedna z pary liczb jest zerem:

for (int i=0; i<32000; i++) { try { b = r.nextInt(); c = r.nextInt(); a = 12345 / (b / c); } catch (ArithmeticException e) { System.out.println("Dzielenie przez 0"); a = 0; }

System.out.println("i: " + i + "a: " + a); }

} }

(14)

Wyświetlanie Opisu Wyjątku

Klasa Throwable przesłania metodę toString() tak

by wyświetlała opis wyjątku.

try { ... }

catch (ArithmeticException e) {

System.out.println("Wyjatek: " + e); a = 0;

(15)

Obsługa Kilku Wyjątków Na Raz

Jeden blok try i kilka catch dla różnych wyjątków.

class WieleBledow {

public static void main(String args[]) { try {

int a = args.length;

System.out.println("a= " + a);

Ryzyko dzielenia przez zero:

int b = 42 / a;

Indeks poza zakresem tablicy:

(16)

Obsługa Kilku Wyjątków Na Raz

Wyłapanie i obsługa błędu dzielenia przez zero:

} catch(ArithmeticException e) {

System.out.println("Dzielenie przez 0");

Wyłapanie i obsługa błędu indeksowania poza tablicą:

} catch(ArrayIndexOutOfBoundsException e) { System.out.println("Index poza tablica"); }

Kod po obsłudze błędów:

System.out.println("Po obsludze bledow"); }

(17)

Kolejność Obsługi Wyjątków

W sekwencji catch, wyjątki pod-klasy muszą wystąpić

przed wyjątkami nad-klasy. Pojawi się błąd kompilacji:

class WyjatekPodKlasa {

public static void main(String args[]) { try { int a = 0; int b = 42 / a; } catch(Exception e) { System.out.println("Wyjatek generyczny"); } catch(ArithmeticException e) { System.out.println("Nieosiagalny"); } } }

(18)

Zagnieżdżony Blok try

Jeden blok try wewnątrz innego try.

class ZagniezdzonyTry {

public static void main(String args[]) {

Zewnętrzny blok try:

try {

int a = args.length;

Ryzyko dzielenia przez zero:

int b = 42 / a;

(19)

Zagnieżdżony Blok try

Wewnętrzny blok try:

try {

Ryzyko dzielenia przez zero:

if (a == 1) a = a /(a-a);

Wykroczenie poza zakres tablicy:

if (a == 2) {

int c[] = {1}; c[42] = 99;

(20)

Zagnieżdżony Blok try

Obsługa wyjątku wykroczenia poza zakres tablicy powstałego w bloku wewnętrznym try:

} catch(ArrayIndexOutOfBoundsException e){ System.out.println("Index za tablica"); }

Obsługa wyjątku błędu dzielenia przez zero powstałego w bloku zewnętrznym try:

} catch (ArithmeticException e) {

System.out.println("Dzielenie przez 0); }

} }

(21)

Zagnieżdżony Blok try

● wyjątek powstaje w bloku wewnętrznym try i jest

obsłużony przez catch w tym samym bloku

● wyjątek powstaje w bloku wewnętrznym try i jest

obsłużony przez catch w bloku zewnętrznym

● wyjątek powstaje w bloku zewnętrznym try i jest

obsłużony przez catch w bloku zewnętrznym

● brakuje instrukcji catch w obu blokach - wyjątek

(22)

Metody i Występowanie Bloków try

class MetodaZagniezdzonyTry {

Metoda z wewnętrznym blokiem try:

static void zagniezdzonyTry(int a) { try { if (a == 1) a = a /(a-a); if (a == 2) { int c[] = {1}; c[42] = 99; } } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Index poza tablica); }

(23)

Metody i Występowanie Bloków try

Metoda z zewnętrznym blokiem try:

public static void main(String args[]) { try { int a = args.length; int b = 42 / a; System.out.println("a= " + a); zagniezdzonyTry(a); } catch (ArithmeticException e) { System.out.println("Dzielenie przez 0); } } }

(24)

Wyrzucanie Wyjątków

Program użytkownika może sam wyrzucać wyjątki:

throw object;

Obiekt musi być klasy Throwable, albo jej pod-klasy.

Uzyskanie obiektu klasy Throwable:

● użycie operatora new

(25)

Obsługa throw

Przerwanie wykonania na instrukcji throw:

● czy najbliższy otaczający blok try posiada

instrukcję catch dla obsługi danego wyjątku?

● w przeciwnym razie, czy kolejny otaczający blok try

posiada tą instrukcję?

● w przeciwnym razie, wykonaj domyślną obsługę

(26)

Demonstracja throw

class ThrowDemo {

static void metoda() { try {

Tworzy nowy wyjątek i go wyrzuca:

throw new NullPointerException("demo");

Wyjątek jest wyłapany natychmiast:

} catch(NullPointerException e) {

(27)

Demonstracja throw

Obsługa polega na przesłaniu wyjątku dalej:

throw e; }

}

Wyjątek jest złapany ponownie przez metodę main:

public static void main(String args[]) { try { metoda(); } catch(NullPointerException e) { System.out.println("Zlapany ponownie"); } } }

(28)

Tworzenie Standardowych Wyjątków

Tworzenie obiektu standardowej klasy wyjątku:

throw new NullPointerException("demo");

Wszystkie standardowe wyjątki mają dwa konstruktory:

● bezparametrowy

● z parametrem String opisującym wyjątek; dostępny

(29)

Deklaracja throws

Jeśli metoda może spowodować wyjątek którego sama nie jest w stanie obsłużyć, to musi ten fakt opisać.

typ nazwa(parametry) throws wyjatki { ... }

Niezbędne jest wymienienie wszystkich wyjątków, oprócz typów Error i RuntimeException.

(30)

Brak Deklaracji throws

Metoda wyrzuca wyjątek którego ani nie wyłapuje, ani nie deklaruje. Ten program nie kompiluje się.

class ThrowsDemo1 {

static void metoda() {

System.out.println("Wewnatrz metody");

throw new IllegalAccessException("demo"); }

public static void main(String args[]) { metoda();

} }

(31)

Dodana Deklaracja throws

Jedna metoda deklaruje, druga wyłapuje wyjątek:

class ThrowsDemo2 {

static void metoda()

throws IllegalAccessException {

System.out.println("Wewnatrz metody");

throw new IllegalAccessException("demo"); }

public static void main(String args[]) { try { metoda(); } catch (IllegalAccessException e) { System.out.println("Zlapany " + e); } } }

(32)

Deklaracja finally

Kod który będzie wykonany po bloku try/catch, bez

względu na powstanie wyjątków.

Użyteczny gdy należy zwolnić zasoby systemowe.

Każdy try musi posiadać co najmniej jedną instrukcję catch lub finally.

(33)

Demonstracja finally

class FinallyDemo {

static void procA() { try {

System.out.println("wewnatrz procA"); throw new RuntimeException("demo"); } finally {

System.out.println("procA: finally"); }

}

static void procB() { try { System.out.println("wewnatrz procB"); return; } finally { System.out.println("procB: finally"); } }

(34)

Demonstracja finally

static void procC() { try { System.out.println("wewnatrz procC"); } finally { System.out.println("procC: finally"); } }

public static void main(String args[]) { try { procA(); } catch(Exception e) { System.out.println("Wyjatek zlapany"); } procB(); procC(); } }

(35)

Standardowe Wyjątki Niesprawdzane

RuntimeException są dostępne automatycznie.

Nie muszą być deklarowane w sekcji throws.

Kompilator nie sprawdza czy metoda deklaruje czy obsługuje te wyjątki.

(36)

Standardowe Wyjątki Niesprawdzane

● ArithmeticException błędy arytmetyczne, np.

dzielenie przez zero

● ArrayIndexOutOfBoundsException indeks

tablicy poza zakresem

● ArrayStoreException przypisanie tablicy

nieodpowiedniego typu elementu

● ClassCastException niepoprawne rzutowanie ● IllegalArgumentException niepoprawny

argument metody

● IllegalMonitorStateException niepoprawna

(37)

Standardowe Wyjątki Niesprawdzane

● IllegalStateException środowisko lub aplikacja

jest w niepoprawnym stanie

● IllegalThreadStateException wymagana

operacja niekompatybilna z bieżącym stanem wątka

● IndexOutOfBoundException jakis rodzaj indeksu

jest poza zakresem

● NegativeArraySizeException tablica tworzona z

ujemnym rozmiarem

● NullPointerException niepoprawne użycie

(38)

Standardowe Wyjątki Niesprawdzane

● NumberFormatException niepoprawna konwersja

stringu na format liczbowy

● SecurityException próba naruszenia

bezpieczeństwa

● StringIndexOutOfBoundsException indeks poza

zakresem stringu

● UnsupportedOperationException napotkano

(39)

Standardowe Wyjątki Sprawdzane

Metody która mogą generować te wyjątki a nie potrafią ich samodzielnie obsłużyć, muszą je deklarować:

● ClassNotFoundException nie znaleziono klasy

● CloneNotSupportedException próba klonowania

obiektu który nie implementuje interfejsu

Cloneable.

● IllegalAccessException dostęp do klasy

zabroniony

● InstantiationException próba tworzenia obiektu

(40)

Standardowe Wyjątki Sprawdzane

● InterruptedException jeden wątek przerwany

przed drugi

● NoSuchFieldException pole nie istnieje

(41)

Tworzenie Własnych Klas Wyjątków

Utwórz pod-klasę Exception.

Pod-klasa nie musi nic deklarować, musi tylko istnieć.

Exception nie deklaruje własnych metod, ale

(42)

Demonstracja Własnych Klas Wyjątków

Własna klasa wyjątków:

class MojWyjatek extends Exception { private int szczegoly;

MojWyjatek(int a) { szczegoly = a;

}

Przesłonięcie metody z klasy Throwable:

public String toString() {

return "MojWyjatek[" + szczegoly + "]"; }

(43)

Demonstracja Własnych Klas Wyjątków

class MojeWyjatki {

Metoda deklaruje wyjątek tej klasy:

static void oblicz(int a) throws MojWyjatek { System.out.println("oblicz(" + a + ")");

Wyrzucenie wyjątku:

if (a > 10) throw new MojWyjatek(a);

System.out.println("Normalne wyjscie"); }

(44)

Demonstracja Własnych Klas Wyjątków

public static void main(String args[]) { try { oblicz(1); oblicz(20); Przechwycenie wyjątku: } catch (MojWyjatek e) { System.out.println("Zlapany " + e); } } }

Cytaty

Powiązane dokumenty

2 lata przy 38 to pestka… Izrael był na finiszu i to właśnie wtedy wybuch bunt, dopadł ich kryzys… tęsknota za Egiptem, za niewolą, za cebulą i czosnkiem przerosła Boże

Profesor Krzysztof Simon, kierownik Kliniki Chorób Zakaźnych i Hepatologii Uniwersytetu Medycznego we Wrocławiu, przyznaje, że młodzi ludzie w stolicy województwa

(główne twierdzenie klasyfikacyjne) 15 Każda skończona grupa prosta jest izomorficzna z jedną z grup z serii (C1) – (C18) lub z jedną ze sporadycznych grup prostych (S1) –

Aplikacja powszechnie nazywana Endomodo to program o pełnej nazwie Endomodo Sports Tracker.. Endomondo jest dostępny na Androida

Aplikacja powszechnie nazywana Endomodo to program o pełnej nazwie Endomodo Sports Tracker.. Endomondo jest dostępny na Androida

(Obowiązkowe!) Utworzyć destruktor rzucający wyjątkiem i napisać program udowadniający, że takie rozwiązanie może prowadzić do niekontrolowanego zakończenia programu przez

Jan Paweł II, utwierdzając braci w wierze w prawdę, utwierdza ich w miłości Prawda bowiem jest dobra, a dobru należy się miłość.. W miłości prawdy tkwi

Z kolekcji Stefana Kiełsz- ni pozostało ponad 140 zdjęć, które zostały zgromadzone w Archiwum Fotografii Ośrod- ka „Brama Grodzka - Teatr