|
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
}
}
|