Jelenlegi hely

18.4 Láncolt kivételek

A kivételeknek sok esetben egy másik kivétel az oka. Ilyen esetben célszerű az eredeti (okozó) kivételt és az új kivételt együtt kezelni. Erre a problémára jelent megoldást a Java 1.4 verzió óta rendelkezésre álló kivételláncolás. Ennek lényege, hogy egy kivétel létrehozásakor becsomagoljuk az okozó kivételt az új kivétel objektumba.

Ennek érdekében két új metódus és két új konstruktor lett hozzáadva a Throwable típushoz.

A következő új metódusok és konstruktorok támogatják a láncolt kivételeket a Throwable osztályban:

Throwable getCause()
Throwable initCause(Throwable)
Throwable(String, Throwable)
Throwable(Throwable)

Az initCause és a Throwable konstruktorok Throwable paramétere egy kivétel, amik okozták az aktuális kivételt. A getCause visszaad egy kivételt, ami okozta az aktuális kivételt, az initCause pedig visszaadja az aktuális kivételt.

A következő példa megmutatja, hogyan használjuk a láncolt kivételeket:

try {
    ...
} catch (IOException e) {
    throw new SampleException("Other IOException", e);
}

Ebben a példában, amikor az IOException-t kap el a program, akkor egy új SampleException kivétel jön létre az eredeti okkal egybekötve, és a kivételek lánca feldobódik egy következő, magasabb szintű kivételkezelőhöz.

Hívási verem információk kinyerése

Most feltételezzünk, hogy egy magasabb szintű kivételkezelő akarja a kimenetre írni a hívási verem tartalmát egyedi formátumban.

Definíció: a hívási verem információt szolgáltat az aktuális szál futási történetéről, az osztályok és a metódusok neveiről, amik akkor hívódnak meg, amikor a kivétel bekövetkezett. A hívási verem egy nagyon hasznos hibakereső eszköz.

A következő kód megmutatja, hogyan kell a getStackTrace metódust használni a kivétel objektumon:

catch (Exception cause) {
    StackTraceElement elements[] = cause.getStackTrace();
    for (int i = 0, n = elements.length; i < n; i++) {      
        System.err.println(elements[i].getFileName() + ":"
               + elements[i].getLineNumber() + ">> "
               + elements[i].getMethodName() + "()");
    }
}

API naplózás

A következő kódrészlet catch blokkjában naplózásra látunk példát. Bármennyire célszerűnek tűnik is az előző példa megközelítése, érdemes inkább a naplózás mechanizmusát alkalmazni a java.util.logging segítségével:

try {
    Handler handler = new FileHandler("OutFile.log");
    Logger.getLogger("").addHandler(handler);
} catch (IOException e) {
    Logger logger = Logger.getLogger("package.name");
    StackTraceElement elements[] = e.getStackTrace();
    for (int i = 0; n = elements.length; i < n; i++) {
        logger.log(Level.WARNING, elements[i].getMethodName());
    }
}