È una cattiva pratica catturare il lancio?

1. Panoramica

In questo tutorial, esamineremo le implicazioni della cattura di Throwable .

2. La classe lanciabile

Nella documentazione Java, la classe Throwable è definita come " la superclasse di tutti gli errori e le eccezioni nel linguaggio Java ".

Diamo un'occhiata alla gerarchia della classe Throwable :

La classe Throwable ha due sottoclassi dirette, vale a dire le classi Error e Exception .

Error e le sue sottoclassi sono eccezioni non verificate, mentre le sottoclassi di Exception possono essere eccezioni selezionate o deselezionate.

Diamo un'occhiata ai tipi di situazioni che un programma può sperimentare quando fallisce.

3. Situazioni recuperabili

Ci sono situazioni in cui il ripristino è generalmente possibile e può essere gestito con sottoclassi selezionate o deselezionate della classe Exception .

Ad esempio, un programma potrebbe voler utilizzare un file che non esiste nella posizione specificata, generando un'eccezione FileNotFoundException controllata .

Un altro esempio è il programma tenta di accedere a una risorsa di sistema senza dover permesso di farlo, con un conseguente incontrollato AccessControl eccezione che sono gettati.

Secondo la documentazione Java, la classe Exception "indica le condizioni che un'applicazione ragionevole potrebbe voler catturare ".

4. Situazioni irrecuperabili

Ci sono casi in cui un programma può entrare in uno stato in cui il ripristino è impossibile in caso di errore. Esempi comuni di ciò sono quando si verifica un overflow dello stack o la JVM esaurisce la memoria.

In queste situazioni, la JVM lancia StackOverflowError e OutOfMemoryError , rispettivamente. Come suggerito dai loro nomi, queste sono sottoclassi della classe Error .

Secondo la documentazione Java, la classe Error "indica problemi seri che un'applicazione ragionevole non dovrebbe cercare di individuare ".

5. Esempio di situazioni recuperabili e irreversibili

Supponiamo di avere un'API che consente ai chiamanti di aggiungere ID univoci a qualche struttura di archiviazione utilizzando il metodo addIDsToStorage :

class StorageAPI { public void addIDsToStorage(int capacity, Set storage) throws CapacityException { if (capacity < 1) { throw new CapacityException("Capacity of less than 1 is not allowed"); } int count = 0; while (count < capacity) { storage.add(UUID.randomUUID().toString()); count++; } } // other methods go here ... }

Diversi potenziali punti di errore possono verificarsi quando si richiama addIDsToStorage :

  • CapacityException: una sottoclasse selezionata di Exception quando si trasmette un valore di capacità inferiore a 1
  • NullPointerException: una sottoclasse non selezionata di Exception se viene fornito un valore di archiviazione null invece di un'istanza di Set
  • OutOfMemoryError - Una sottoclasse di errore non selezionata se la JVM esaurisce la memoria prima di uscire dal ciclo while

Le situazioni CapacityException e NullPointerException sono errori da cui il programma può ripristinarsi, ma OutOfMemoryError è irrecuperabile.

6. Cattura lanciabile

Supponiamo che l'utente dell'API catturi Throwable solo nel try-catch quando chiama addIDsToStorage :

public void add(StorageAPI api, int capacity, Set storage) { try { api.addIDsToStorage(capacity, storage); } catch (Throwable throwable) { // do something here } }

Ciò significa che il codice chiamante reagisce allo stesso modo a situazioni recuperabili e irrecuperabili.

La regola generale nella gestione delle eccezioni è che il blocco try-catch deve essere il più specifico possibile nella cattura delle eccezioni. Cioè, uno scenario generico deve essere evitato .

Il Catching Throwable nel nostro caso viola questa regola generale. Per reagire separatamente a situazioni recuperabili e irrecuperabili, il codice chiamante dovrebbe ispezionare l'istanza dell'oggetto Throwable all'interno del blocco catch .

Il modo migliore sarebbe utilizzare un approccio specifico nella gestione delle eccezioni ed evitare di cercare di affrontare situazioni irrecuperabili .

7. Conclusione

In questo articolo, abbiamo esaminato le implicazioni della cattura di Throwable in un blocco try-catch .

Come sempre, il codice sorgente completo dell'esempio è disponibile su Github.