Exception.getCause în Java

Returnează excepția originală care a produs-o pe aceasta (lanț de excepții), sau null dacă nu există.

Sintaxă
Throwable getCause()
Throwable initCause(Throwable cauza)
Exception(String mesaj, Throwable cauza)

Ce face Exception.getCause

Când prinzi o excepție de nivel jos și arunci una mai clară pentru cine te apelează, păstrezi excepția originală ca cauză: throw new ServiciuException("nu pot încărca profilul", e). Așa nu se pierde informația despre ce s-a întâmplat de fapt.

getCause() returnează această excepție originală sau null. Cauza poate avea la rândul ei o cauză, deci poți parcurge tot lanțul până la eroarea inițială. Multe clase ale JDK fac asta: ExecutionException și CompletionException învelesc excepția sarcinii, UncheckedIOException învelește o IOException.

Parametri

Parametru Descriere
cauza Excepția originală, dată în constructor sau prin initCause.

Ce returnează

Un Throwable sau null.

Exemple

Exemplul 1: Lanț de excepții parcurs până la capăt

public class Main {
    static class ProfilException extends Exception {
        private static final long serialVersionUID = 1L;

        ProfilException(String mesaj, Throwable cauza) {
            super(mesaj, cauza);
        }
    }

    static int varsta(String text) {
        try {
            return Integer.parseInt(text);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("câmpul vârstă este greșit", e);
        }
    }

    static void incarcaProfil(String varstaText) throws ProfilException {
        try {
            System.out.println("Vârstă: " + varsta(varstaText));
        } catch (IllegalArgumentException e) {
            throw new ProfilException("nu pot încărca profilul Anei", e);
        }
    }

    public static void main(String[] args) {
        try {
            incarcaProfil("2O");
        } catch (ProfilException e) {
            for (Throwable t = e; t != null; t = t.getCause()) {
                System.out.println(t.getClass().getSimpleName() + ": " + t.getMessage());
            }
        }
    }
}

Rezultat

ProfilException: nu pot încărca profilul Anei
IllegalArgumentException: câmpul vârstă este greșit
NumberFormatException: For input string: "2O"

Exemplul 2: Cauza din ExecutionException

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
            Future<Integer> f = executor.submit(() -> Integer.parseInt("12,5"));
            try {
                f.get();
            } catch (ExecutionException e) {
                System.out.println("Excepția prinsă: " + e.getClass().getSimpleName());
                System.out.println("Cauza reală: " + e.getCause());
            }
        }
    }
}

Rezultat

Excepția prinsă: ExecutionException
Cauza reală: java.lang.NumberFormatException: For input string: "12,5"

Exemplul 3: Fără cauză: null

public class Main {
    public static void main(String[] args) {
        Exception simpla = new Exception("eroare simplă");
        System.out.println("Cauza: " + simpla.getCause());
        Exception cuCauza = new Exception("eroare de sus");
        cuCauza.initCause(new ArithmeticException("împărțire la zero"));
        System.out.println("Cauza: " + cuCauza.getCause());
    }
}

Rezultat

Cauza: null
Cauza: java.lang.ArithmeticException: împărțire la zero

Greșeli frecvente

  • Arunci o excepție nouă fără cauză: throw new RuntimeException("eroare") în catch. Pierzi informația despre eroarea originală; transmite e ca al doilea argument.
  • Apelezi getCause().getMessage() fără să verifici null. Nu orice excepție are cauză.

Comenzi înrudite

  • Exception: Clasa de bază pentru erorile pe care un program le poate trata; getMessage() returnează mesajul dat la creare.
  • RuntimeException: Clasa de bază a excepțiilor neverificate: nu trebuie declarate cu throws și nici prinse obligatoriu.
  • Future: Rezultatul unei sarcini care rulează pe alt fir: get() așteaptă și îl returnează, isDone() spune dacă s-a terminat.
  • CompletableFuture.exceptionally: Tratează o eroare din lanț: dacă un pas anterior a eșuat, funcția primește excepția și returnează o valoare de rezervă.