Domanda

è una brutta pratica catturare Throwable?

Ad esempio qualcosa del genere:

try {
    // Some code
} catch(Throwable e) {
    // handle the exception
}
.

È una cattiva pratica o dovremmo essere il più specifiche possibile?

È stato utile?

Soluzione

È necessario essere il più specifico possibile.I bug imprevisti potrebbero insinuarsi in questo modo.

inoltre, Throwable copre Error pure e questo di solito nessun punto di ritorno .Non vuoi catturare / gestirlo, vuoi che il tuo programma morisse immediatamente in modo da poterlo aggiustare correttamente.

Altri suggerimenti

Questa è una cattiva idea. In effetti, anche la cattura del Exception è solitamente una cattiva idea. Consideriamo un esempio:

try {
    inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
    inputNumber = 10; //Default, user did not enter valid number
}
.

Ora, diciamo che GetUserInput () blocca i blocchi per un po 'e un altro thread interrompe il tuo thread nel modo peggiore possibile (chiama Thread.Stop ()). Il blocco di cattura catturerà un errore ThreadDeath. Questo è super cattivo. Il comportamento del tuo codice dopo aver catturato tale eccezione è in gran parte indefinito.

Un problema simile si verifica con l'eccezione di cattura. Forse getUserInput() non è riuscito a causa di un'interrupamentoException o un'autorizzazione negata un'eccezione durante il tentativo di registrare i risultati o tutti i tipi di altri fallimenti. Non hai idea di cosa sia andato storto, come per questo, non hai anche idea di come risolvere il problema.

Hai tre opzioni migliori:

1 - Cattura esattamente l'eccezione (i) sai come gestire:

try {
    inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
    inputNumber = 10; //Default, user did not enter valid number
}
.

2 - Rethrow Qualsiasi eccezione si imbatté e non so come gestire:

try {
    doSomethingMysterious();
} catch(Exception e) {
    log.error("Oh man, something bad and mysterious happened",e);
    throw e;
}
.

3 - Utilizzare un blocco finalmente in modo da non dover ricordare di ritornare:

 Resources r = null;
 try {
      r = allocateSomeResources();
      doSomething(r);
 } finally {
     if(r!=null) cleanUpResources(r);
 }
.

Tieni anche consapevole che quando cattura Throwable, è anche possibile catturare InterruptedException che richiede un trattamento speciale.Vedi Affrontare l'interruzioneException per ulteriori dettagli. Se vuoi solo prendere le eccezioni deselezionate, potresti anche considerare questo motivo

try {
   ...
} catch (RuntimeException exception) {
  //do something
} catch (Error error) {
  //do something
}
.

In questo modo, quando si modifica il codice e aggiungi una chiamata al metodo che può lanciare un'eccezione controllata, il compilatore ti ricorderà questo e quindi puoi decidere cosa fare per questo caso.

Dritto dal Javadoc della classe di errore (che raccomanda di non catturare questi):

 * An <code>Error</code> is a subclass of <code>Throwable</code> 
 * that indicates serious problems that a reasonable application 
 * should not try to catch. Most such errors are abnormal conditions. 
 * The <code>ThreadDeath</code> error, though a "normal" condition,
 * is also a subclass of <code>Error</code> because most applications
 * should not try to catch it. 

 * A method is not required to declare in its <code>throws</code> 
 * clause any subclasses of <code>Error</code> that might be thrown 
 * during the execution of the method but not caught, since these 
 * errors are abnormal conditions that should never occur. 
 *
 * @author  Frank Yellin
 * @version %I%, %G%
 * @see     java.lang.ThreadDeath
 * @since   JDK1.0
.

Non è una brutta pratica se non puoi assolutamente avere una bolla di eccezione da un metodo.

È una brutta pratica se non riesci a gestire l'eccezione.Meglio aggiungere "Gruppi" alla firma del metodo che catturare e ri-lanciare o, peggio, avvolgerlo in un runtimesexception e ri-lanciare.

Catching Throwable è talvolta necessario se si utilizzano librerie che lanciano errori eccessivamente entusiasticamente, altrimenti la tua libreria potrebbe uccidere la tua applicazione.

Tuttavia, sarebbe meglio in queste circostanze specificare solo gli errori specifici lanciati dalla biblioteca, anziché tutti i gettati.

Throwable è la classe base per tutte le classi di quelle che possono essere lanciate (non solo eccezioni).C'è poco che tu possa fare se prendi un outofmemoryerror o kernelerror (vedi quando catturare Java.Lang.Error? )

Le eccezioni di cattura dovrebbero essere sufficienti.

dipende dalla tua logica o da essere più specifiche per le opzioni / possibilità.Se c'è qualche eccezione specifica che puoi reagire in modo significativo, potresti prenderlo prima e farlo.

Se non ce n'è e sei sicuro che farai la stessa cosa per tutte le eccezioni e gli errori (ad esempio uscire con un messaggio di errore), rispetto a quello che non è un problema per catturare il Throable.

Di solito il primo caso si tiene e non avresti tagliato il gestore.Ma ci sono ancora un sacco di casi in cui catturarlo funziona bene.

Sebbene sia descritta come una pessima pratica, a volte puoi trovare casi rari che non solo utili ma anche obbligatorio. Ecco due esempi.

In un'applicazione Web in cui è necessario mostrare una pagina di errore completo dell'utente. Questo codice assicura che ciò accada in quanto è un grande try/catch attorno a tutte le vostre esigenze di richiesta (servlet, azioni montanti o qualsiasi controller ....)

try{
     //run the code which handles user request.
   }catch(Throwable ex){
   LOG.error("Exception was thrown: {}", ex);
     //redirect request to a error page. 
 }
.

}

Come un altro esempio, considera di avere una classe di servizio che serve attività di trasferimento del fondo. Questo metodo restituisce un TransferReceipt se il trasferimento è fatto o NULL se non poteva.

String FoundtransferService.doTransfer( fundtransferVO);
.

Ora Imaging Ottieni un List dei trasferimenti di fondi dall'utente e devi utilizzare il servizio sopra per farli tutti.

for(FundTransferVO fundTransferVO : fundTransferVOList){
   FoundtransferService.doTransfer( foundtransferVO);
}
.

Ma cosa succederà se qualsiasi eccezione avviene? Non dovresti fermarti, poiché un trasferimento potrebbe essere stato successo e uno potrebbe non essere, dovresti continuare a superare tutti gli utenti List e mostrare il risultato a ciascun trasferimento. Quindi finisci con questo codice.

for(FundTransferVO fundTransferVO : fundTransferVOList){
    FoundtransferService.doTransfer( foundtransferVO);
 }catch(Throwable ex){
    LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex);
  }
}
.

Puoi sfogliare molti progetti open source per vedere che il throwable è davvero memorizzato nella cache e gestito. Ad esempio, qui è una ricerca di tomcat, struts2 e primefaces:

https://github.com/ Apache / Tomcat / Search? UTF8=% E2% 9C% 93 & AMP; Q= Catch% 28 Discobile https://github.com/apache/stuts / cerca? utf8=% E2% 9C% 93 & q= catch% 28 Drownable https://github.com/primefeces/primefeces / cerca? utf8=% E2% 9C% 93 e amp; q= catch% 28 Drownable

La domanda è un po 'vaga; Stai chiedendo "Va bene catturare Throwable", o "va bene prendere un Throwable e non fare nulla"? Molte persone hanno risposto a quest'ultimo, ma questo è un problema laterale; Il 99% del tempo non si dovrebbe "consumare" o scartare l'eccezione, indipendentemente dal fatto che si stia catturando Throwable o IOException o qualsiasi altra cosa.

Se si propaga l'eccezione, la risposta (come la risposta a così tante domande) è "dipende". Dipende da cosa stai facendo con l'eccezione, perché lo stai prendendo.

Un buon esempio del motivo per cui vorresti catturare Throwable è fornire una sorta di pulizia se c'è qualche errore. Ad esempio in JDBC, se si verifica un errore durante una transazione, si desidera riportare la transazione:

try {
  …
} catch(final Throwable throwable) {
  connection.rollback();
  throw throwable;
}
.

Si noti che l'eccezione non viene scartata, ma propagata.

Ma come politica generale, catturando Throwable perché non hai una ragione e sono troppo pigri per vedere quali specifiche eccezioni vengono lanciate è una forma scarsa e una cattiva idea.

In generale, si desidera evitare di catturare i generatori di generatori ma posso pensare (almeno) due casi specifici in cui è appropriato farlo:

    .
  • Si desidera spegnere l'applicazione in risposta agli errori, in particolare Error che è altrimenti innocuo.
  • Stai implementando un meccanismo di filo-filo simile a exetroorservice.submit () che richiede di inoltrare le eccezioni all'industria in modo da poterlo gestire.

Se usiamo buhisable , quindi copre anche un errore e questo è così.

Esempio.

    public class ExceptionTest {
/**
 * @param args
 */
public static void m1() {
    int i = 10;
    int j = 0;
    try {
        int k = i / j;
        System.out.println(k);
    } catch (Throwable th) {
        th.printStackTrace();
    }
}

public static void main(String[] args) {
    m1();
}
.

}

Uscita:

java.lang.ArithmeticException: / by zero
at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12)
at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)
.

Throwable è la superclass di tutti gli errori ed esecuzioni. Se si utilizza Thankable in una clausola di cattura, non solo catturerà tutte le eccezioni, catturerà anche tutti gli errori.Gli errori vengono lanciati dal JVM per indicare gravi problemi che non sono destinati a essere gestiti da un'applicazione.Esempi tipici per questo sono gli OutochmoryError o lo Stackoverflowerror.Entrambi sono causati da situazioni che sono al di fuori del controllo dell'applicazione e non possono essere gestite.Quindi non dovresti catturare i buglioni a meno che non sia abbastanza fiducioso che sarà solo un'eccezione risiedere all'interno di Throable.

Mentre è generalmente cattiva pratica catturare throwable (come chiarito dalle numerose risposte su questa domanda), gli scenari in cui catturare Throwable è utile sono abbastanza comuni. Lasciami spiegare una causa del genere che uso al mio lavoro, con un esempio semplificato.

Considera un metodo che esegue l'aggiunta di due numeri e dopo un'aggiunta di successo, invia un avviso e-mail a determinate persone. Supponiamo che il numero restituito sia importante e utilizzato dal metodo di chiamata.

public Integer addNumbers(Integer a, Integer b) {
    Integer c = a + b;          //This will throw a NullPointerException if either 
                                //a or b are set to a null value by the
                                //calling method
    successfulAdditionAlert(c);
    return c;
}

private void successfulAdditionAlert(Integer c) {
    try {
        //Code here to read configurations and send email alerts.
    } catch (Throwable e) {
        //Code to log any exception that occurs during email dispatch
    }
}
.

Il codice per inviare avvisi e-mail legge molte configurazioni di sistema e quindi potrebbero esserci una varietà di eccezioni lanciate da quel blocco di codice. Ma non vogliamo alcuna eccezione incontrata durante la spedizione di avviso per propagare al metodo del chiamante, poiché tale metodo è semplicemente interessato alla somma dei due valori integer che fornisce. Quindi, il codice per la spedizione degli avvisi e-mail viene inserito in un blocco try-catch, in cui viene catturato Throwable e qualsiasi eccezione è semplicemente registrata, consentendo al resto del flusso di continuare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top