WYJĄTKI



Tradycyjna obsługa błędów

Problemy


PROSTY SCHEMAT OBSŁUGI WYJĄTKÓW W JAVIE

Wyjątek powstaje na skutek jakiegoś nieoczekiwanego błędu.
Wyjątek jest zgłaszany.
Wyjątek jest obsługiwany.

int a, b, c;
String s;
try {                                    // w bloku try ujmujemy instrukcje, które mogą spowodować wyjątek
         a = b/c;                       // jeżeli np. c = 0, zostanie zgłoszony wyjątek ArithmeticException
         s = Integer.toString(a);
} catch(ArithmeticException ex) {  // wyjątek jest obsługiwany w bloku catch
     s = "*" ;
     }

Uwaga: w przypadku operacji na liczbach rzeczywistych przy dzieleniu przez 0 wyjątek nie zostanie zgłoszony, a wartość wyniku będzie POSITIVE_INFINITY (lub NEGATIVE_INFINITY), co po przeskztałceniu w String da napis "Infinity" ("-Infinity").

KLASY WYJĄTKÓW

Wyjątki są obiektami klas wyjątków.


             (Żródło: Peter Haggar, Java Exception Handling, IBM 1999)
 
 

WYJĄTKI KONTROLOWANE I NIEKONTROLOWANE


Przykład:

 FileInputStream in  = null;
 FileOutputStream out = null;

 try {
   in  = new FileInputStream(args[0]);
   out = new FileOutputStream(args[1]);
   int c = 0;
   while ((c = in.read()) != -1) out.write(c);

 } catch(FileNotFoundException exc) {
   System.out.println("Plik " + args[0] + " nie istnieje.");
   System.exit(1);

 } catch(IOException exc) {
   System.out.println(exc.getMessage());
   System.exit(1);

Gdybyśmy napisali metodę kopiującą strumienie:

public static void copyStream(InputStream in, OutputStream out)
              throws IOException {

  int c = 0;
  while ((c = in.read()) != -1) out.write(c);
}

to obsługa wyjątku IOException, który może powstać przy read() musiałaby być prowadzona w miejscu wywołania metody:

try {
   .....
   copyStream(in, out);
} catch(IOException exc) { ...  }
 
 


SEKWENCJA DZIAŁANIA


KLAUZULA FINALLY

Klauzula finally służy do wykonania kodu niezależnie od tego czy wystąpił wyjątek czy nie.

boolean metoda(...) {
try {
       // instrukcje, które mogą spowodować wyjątek
}
catch(Exception e) {  return false; }
finally {
       // uporządkowanie, np. zamknięcie pliku
       }
return true;
}

Jeśli powstał wyjątek - uruchamiana jest klauzula catch.
Mimo, iż zmienia ona sekwencję sterowania (zwraca false na znak, iż nastąpiło niepowodzenie), sterowanie przekazywane jest do klauzuli finally. I dopiero potem zwracany jest wynik - false.
Jeśli nie było wyjątku, po zakończeniu instrukcji w bloku try sterowanie od razu wchodzi do klauzuli finally, a po jej zakończeniu zwracany jest wynik true (wykonywana jest ostatnia instrukcja metody).
 


WŁASNE WYJĄTKI

Wyjątki są obiektami klas pochodnych od Throwable.
Żeby stworzyć własny wyjątek należy zdefiniować odpowiednią klasę.
Zgodnie z konwencją dziedziczymy podklasę Throwable - klasę Exception.

class NaszWyj extends Exception {
...
}

Zwykle w naszej klasie wystarczy umieścić dwa konstruktory: bezparametrowy oraz z jednym argumentem = komunikat o przyczynie powstania wyjątku.

Użycie wyjątku: