Mariusz Prowaźnik

o programowaniu w Javie, Scali i Clojure.


Obsługa wyjątków: Finally

Słowo kluczowe finally stosujemy, gdy chcemy, by jakaś część kodu wykonała się niezależnie od tego, czy w bloku try-catch zostanie wyrzucony wyjątek. Zatem po wykonaniu takiego kodu:

public class Test {
 public static void main(String[] args) {
  try {
   String a = null;
   System.out.println(a.charAt(0));
  } catch (NullPointerException ex) {
   System.out.println("Null pointer!");
  } finally {
   System.out.println("Hello world!");
  }
 }
}
otrzymamy:
Null pointer!
Hello world!
Gdyby zmienić String a = null na String a ="arbuz" otrzymamy:
a
Hello world!
Wydawałoby się, że na tym można skończyć pisać o try-finally, jednak istnieje kilka ciekawych przypadków, o których do niedawna nie wiedziałem. Np. kod w bloku finally wykona się nawet jeśli w bloku try zostanie zamieszczona instrukcja kończąca wykonanie metody i zwracająca wartość return:
package com.blogspot.evojava;

public class Test {
 public static void main(String[] args) {
  try {
   return;
  } finally {
   System.out.println("Hello world!");
  }
 }
}
Wynik:
Hello world!
Podobnie jest w przypadku instrukcji typu break, continue:
package com.blogspot.evojava;

public class App {
 public static void main(String[] args) {
  for (int i = 0; i < 5; i++) {
   System.out.println("Hello World! " + i);
   try {
    break;
   } finally {
    continue;
   }
  }
 }
Hello World! 0
Hello World! 1
Hello World! 2
Hello World! 3
Hello World! 4
Jedynym sposobem, żeby "powstrzymać" finally jest zamknięcie JVM za pomocą System.exit(0):
package com.blogspot.evojava;

public class Test {
 public static void main(String[] args) {
  try {
   System.exit(0);
  } finally {
   System.out.println("Hello world!");
  }
 }

Należy pamiętać też o tym, że jeśli w bloku finally zostanie wyrzucony wyjątek, to dalsze przetwarzanie zostanie przerwane:
package com.blogspot.evojava;

public class Test {
 public static void main(String[] args) throws Exception {
  String str = null;
  try {
  } finally {
   str.compareTo("a");
   System.out.println(" world!");
  }
 }
Exception in thread "main" java.lang.NullPointerException
 at com.blogspot.evojava.Test.main(Test.java:8)
I pozostaje jeszcze inna ważna sprawa: niepoprawne skonstruowanie bloku try-finally może skutkować bardzo niebezpiecznym dla programu błędem. Przykład podany jest poniżej:
package com.blogspot.evojava;

public class Test {
 public static void main(String[] args) throws Exception {
  try {
   throw new Exception("Ważny wyjątek");
  } finally {
   throw new Exception("Nieistotny wyjątek");
  }
 }
}
Exception in thread "main" java.lang.Exception: Nieistotny wyjątek
 at com.blogspot.evojava.Test.main(Test.java:8)
W kodzie tym jeden z wyjątków w ogóle nie został obsłużony, ani nigdzie nie został przekazany. Mógłby być powodem złego działania programu, a programista w ogóle by się o nim nie dowiedział, bo wszelki ślad po wyjątku zaginął. W bardziej skomplikowanym kodzie taki błąd może być bardzo kosztowny i trudny do odnalezienia. Dlatego warto wiedzieć o takim przypadku.

Brak komentarzy :

Prześlij komentarz