Java - Obsługa wyjątków w Javie
Podczas działania każdego programu mogą wystąpić błędy: wyjątki (ang. exceptions),
jak np. dzielenie przez zero lub próba otwarcia nieistniejącego pliku.
Java posiada mechanizm obsługi takich wyjątków poprzez wywoływaniem procedur obsługi błędów.
wystąpienie błędu - wyjątku - powoduje przerwanie wykonywania programu.
Mechanizm obsługi wyjątków umożliwia
zaprogramowanie obsługi sytuacji błędnych, dzięki czemu program nie przerwie wykonywania po wystąpieniu
błędu, ale może zignorować lub skorygować operację, która spowodowała wyjątek.
W Javie sytuacja wyjątkowa występuje wtedy, gdy program wykona instrukcję throw. Wyrażenie throw przekazuje sterowanie do skojarzonego z nim bloku catch: bloku obsługującego wystąpienie sytuacji wyjątkowej. Brak bloku catch w aktualnie wykonywanej metodzie powoduje przekazanie sterowania - bez zwracania wartości - do metody, która wywołała aktualną metodę. Jeśli w tej metodzie blok catch zostanie znaleziony, to jest on wykonywany. W przeciwnym razie sterowanie przekazywane jest do metody, która wywołała tę metodę zgodnie z łańcuchem wywołań metod. Dzieje się tak do momentu znalezienia bloku catch odpowiedzialnego za obsługę wyjątku. Wszystkie wyjątki, które występują w programie muszą być podklasą klasy Throwable. Struktura (fragmentu) programu z obsługą wyjątków: ..... try { // ciąg instrukcji, które mogą spowodować wystąpienie wyjątku } catch (ObiektThrowable nazwaZmiennej) { // blok instrukcji obsługi sytuacji wyjątkowej // wykonywany tylko, gdy typu wyjątku jest identyczny // z typem zmiennej będącej parametrem bloku } catch (ObiektThrowable nazwaZmiennej) { . . . } catch (ObiektThrowable nazwaZmiennej) { . . . } finally // opcjonalnie { // blok instrukcji wykonywanych zawsze przed opuszczeniem metody // również wtedy, gdy blok try zawiera instrukcję // return lub spowodował wystąpienie wyjątku } ..... Wystąpienie wyjątku powoduje wykonanie tylko jednego bloku catch. Ponieważ wyjątki mają różny "zasięg": od najogólniejszego: Exception, poprzez konkretne (IOException,...), aż po własne - zdefiniowane przez programistę, to należy pamiętać o umieszczeniu bloków obsługujących poszczególne sytuacje wyjątkowe w odpowiedniej kolejności: od najbardziej szczegółowych na początku, do najogólniejszych na końcu. W przeciwnym wypadku zawsze byłby wykonany blok najbardziej ogólny. Najczęściej jednak zła kolejność umieszczenia bloków catch wykrywana jest przez kompilator i sygnalizowania odpowiednim komunikatem błędu. Przykład programu wywołującego sytuację wyjątkową: public class wyjatki { public static void main (String args[]) { Tab tab = new Tab(); // utworzenie obiektu klasy Tab for (int x=0 ; x<15 ; x++) // wyświetlanie kolejnych // elementów tabeli // dla n=10 wystąpi błąd, // bo nie ma takiego elementu System.out.println("T[" + x + "] = " + tab.podajElement(x)); } } class Tab { int tab[]; public Tab() // konstruktor klasy { tab = new int[10]; // tworzy tabelę o 10 elementach for (int i=0 ; i<10 ; i++) tab[i] = i*i; // przypisuje wartości elementom tabeli } int podajElement(int n) { int retVal = 0; try // zwraca element n { retVal = tab[n]; } catch (ArrayIndexOutOfBoundsException e) // wykonywane dla n > 9 { System.out.println("Nie ma elementu tabeli o numerze " + n); System.exit(1); } return retVal; } } W powyższym przykładzie program dla n=10 wywoła procedurę obsługi wyjątków, która wyświetli stosowny komunikat i program zakończy działanie. Spróbujmy jednak przerobić ten program tak, aby po wystąpieniu błędu pojawiał się tylko komunikat, ale program pracował nadal. W tym celu przeniesiemy procedurę obsługi błędu do metody main oraz dodamy metodę finally. Pozwoli to kontynuować program mimo wystąpienia kolejnych sytuacji wyjątkowych. W przykładzie tym utworzone są dwie procedury catch do obsługi błędu: 1-sz będzie wykonywana tylko wtedy, gdy podany indeks tablicy przekroczy dopuszczalny zakres; 2-ga - w każdym innym wypadku (w tym programie inny błąd nie może wystąpić, ale ma to być tylko przykład). Ważna jest przy tym kolejność obu procedur catch: gdybyśmy ja zmienili, to podczas kompilacji wystąpi błąd, ponieważ catch (Exception e) wyczerpuje wszystkie możliwe sytuacje wyjątkowe i umieszczenie za nią jakiejkolwiek innej procedury obsługi wyjątków jest błędem. public class wyjatki { public static void main (String args[]) { Tab tab = new Tab(); int x; for (int n=0 ; n<15 ; n++) { try { x = -1; x = tab.podajElement(n); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Nie ma elementu o numerze " + n); } catch (Exception e) { System.out.println("Jakiś błąd!"); } finally { if (value!=-1) System.out.println("Element nr 20 to: " + x); } } } } class Tab { int tab[]; public Tab() // konstruktor klasy { tab = new int[10]; // tworzy tabelę o 10 elementach for (int i=0 ; i<10 ; i++) tab[i] = i*i; // przypisuje wartości elementom tabeli } int podajElement(int n) { return tab[n]; // zwraca n-ty element tabeli // dla n < 0 lub > 9 spowoduje błąd } }
|