Est-ce une mauvaise pratique pour attraper Lancable?

est-ce une mauvaise pratique d'attraper Throwable ?

par exemple quelque chose comme ceci:

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

Est-ce une mauvaise pratique ou nous devrions être aussi précis que possible?

81
demandé sur chrylis 2011-05-21 21:14:19

14 réponses

vous devez être aussi spécifique que possible. Sinon, des bugs imprévus pourraient s'échapper de cette façon.

D'ailleurs, Throwable couvre Error ainsi que généralement pas de point de retour . Vous ne voulez pas attraper / gérer cela, vous voulez que votre programme meurt immédiatement afin que vous puissiez le réparer correctement.

79
répondu BalusC 2017-05-23 10:31:31

C'est une mauvaise idée. En fait, même attraper Exception est généralement une mauvaise idée. Prenons un exemple:

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

maintenant, disons que getUserInput () bloque pendant un moment, et qu'un autre thread arrête votre thread de la pire façon possible (il appelle thread.arrêter.) )( Votre bloc catch va enregistrer une erreur ThreadDeath . C'est super mauvais. Le comportement de votre code après avoir saisi cette Exception est largement indéfini.

A similaire problème se produit avec la capture Exception. Peut-être que getUserInput() a échoué à cause d'une InterruptException, ou une permission refusée exception tout en essayant d'enregistrer les résultats, ou toutes sortes d'autres échecs. Vous n'avez aucune idée de ce qui s'est passé, à cause de cela, vous aussi vous n'avez aucune idée de comment résoudre le problème.

vous avez trois meilleures options:

1 -- Attraper exactement l'Exception(s) vous savez comment le gérer:

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

2 -- Renvoyer une exception vous de courir et ne sais pas comment gérer:

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

3-Utilisez un bloc final pour ne pas avoir à vous souvenir de rethrow:

 Resources r = null;
 try {
      r = allocateSomeResources();
      doSomething(r);
 } finally {
     if(r!=null) cleanUpResources(r);
 }
32
répondu Brandon Yarbrough 2011-05-21 17:38:51

sachez aussi que lorsque vous attrapez Throwable , vous pouvez aussi attraper InterruptedException qui nécessite un traitement spécial. Voir concernant L'Exception D'interruption pour plus de détails.

si vous voulez seulement attraper des exceptions non vérifiées, vous pourriez également considérer ce modèle

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

de cette façon, quand vous modifiez votre code et ajoutez un appel de méthode qui peut jeter une exception cochée, le compilateur vous rappellera de cela et ensuite, vous pouvez décider quoi faire pour ce cas.

19
répondu gawi 2013-04-16 01:44:08

Ce n'est pas une mauvaise pratique si vous ne pouvez absolument pas une exception bulle d'une méthode.

c'est une mauvaise pratique si vous ne pouvez vraiment pas gérer l'exception. Mieux vaut ajouter "jette" à la signature de la méthode que simplement attraper et re-jeter ou, pire, envelopper dans une RuntimeException et re-jeter.

12
répondu duffymo 2011-05-21 17:20:13

directement du javadoc de la classe D'erreur (qui recommande de ne pas les attraper):

 * 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
12
répondu Andrew Norman 2015-09-18 16:08:49

attraper Lancable est parfois nécessaire si vous utilisez des bibliothèques qui jettent des erreurs trop-avec enthousiasme, sinon votre bibliothèque peut tuer votre application.

cependant, il serait préférable dans ces circonstances de spécifier seulement les erreurs spécifiques lancées par la bibliothèque, plutôt que tous les Lancables.

7
répondu DNA 2015-06-16 12:25:16

Lancable est la classe de base pour toutes les classes qui peuvent être lancées (pas seulement des exceptions). Il y a peu que vous pouvez faire si vous attrapez un OutOfMemoryError ou KernelError (voir quand attraper java.lang.D'erreur? )

d'intercepter les Exceptions devrait être suffisant.

5
répondu ic3 2017-05-23 12:26:26

cela dépend de votre logique ou d'être plus spécifique à vos options / possibilités. S'il y a une exception spécifique sur laquelle vous pouvez éventuellement réagir de manière significative, vous pouvez l'attraper en premier et le faire.

S'il n'y a pas et vous êtes sûr que vous ferez la même chose pour toutes les exceptions et les erreurs (par exemple sortir avec un message d'erreur), que ce n'est pas un problème pour attraper le lancable.

D'habitude le premier cas tient et vous ne voulez pas attraper le lancer. Mais il y a encore beaucoup de cas où l'attraper fonctionne bien.

4
répondu b.buchhold 2011-05-21 17:19:17

bien qu'il soit décrit comme une très mauvaise pratique, vous pouvez parfois trouver rare cas qu'il non seulement utile, mais aussi obligatoire. Voici deux exemples.

dans une application web où vous devez montrer une signification pleine page d'erreur à l'utilisateur. Ce code s'assure que cela se produit car il s'agit d'un grand try/catch autour de tous vos handelers de requêtes ( servlets, actions struts, ou n'importe quel contrôleur ....)

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

}

autre exemple, considérez que vous avez une catégorie de services qui sert les entreprises de transfert de fonds. Cette méthode retourne un TransferReceipt si le transfert est fait ou NULL si elle ne pouvait pas.

String FoundtransferService.doTransfer( fundtransferVO);

maintenant imaging vous obtenez un List de transferts de Fonds de l'utilisateur et vous devez utiliser le service ci-dessus pour les faire tous.

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

mais que se passera-t-il si n'importe quelle exception se produit? Vous ne devriez pas arrêtez, comme un transfert peut avoir été un succès et un ne peut pas, vous devez garder aller à travers tous les utilisateurs List , et de montrer le résultat à chaque transfert. Si vous vous retrouvez avec ce code.

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

vous pouvez parcourir beaucoup de projets open source pour voir que le throwable est vraiment caché et manipulé. Par exemple, voici une recherche de tomcat , struts2 et primefaces :

https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable

4
répondu Alireza Fattahi 2015-12-13 05:03:44

bien qu'il soit généralement de mauvaise pratique d'attraper Lanceable (comme l'expliquent les nombreuses réponses à cette question), les scénarios où la capture Throwable est utile sont assez fréquents. Laissez-moi vous expliquer un tel cas que j'utilise à mon travail, avec un exemple simplifié.

envisager une méthode qui effectue l'ajout de deux numéros, et après l'ajout réussi, il envoie une alerte par courriel à certaines personnes. Supposons que le nombre retourné est important et utilisé par l' l'appel de la méthode.

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
    }
}

le code pour envoyer des alertes e-mail lit beaucoup de configurations de système et donc, il pourrait y avoir une variété d'exceptions lancées à partir de ce bloc de code. Mais nous ne voulons pas qu'aucune exception rencontrée lors de l'envoi d'alertes se propage à la méthode de l'appelant, car cette méthode concerne simplement la somme des deux valeurs entières qu'elle fournit. Par conséquent, le code pour envoyer des alertes par courriel est placé dans un bloc try-catch , où Throwable est les captures et les exceptions sont simplement enregistrées, ce qui permet au reste du flux de continuer.

0
répondu CodeNewbie 2015-06-16 10:50:14

si nous utilisons lancable , alors il couvre erreur ainsi et c'est tout.

exemple.

    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();
}

}

sortie:

java.lang.ArithmeticException: / by zero
at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12)
at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)
0
répondu VicXj 2017-09-15 09:57:08

Lancable est la superclasse de toutes les erreurs et des dépassements. Si vous utilisez Throwable dans une clause catch, elle ne saisira pas seulement toutes les exceptions, elle saisira aussi toutes les erreurs. Les erreurs sont lancées par la JVM pour indiquer des problèmes graves qui ne sont pas destinés à être traités par une application. Les exemples typiques sont le OutOfMemoryError ou le StackOverflowError. Les deux sont causées par des situations qui sont hors du contrôle de l'application et ne peuvent pas être manipulées. Donc tu ne devrais pas catch Throwables à moins que vous êtes assez confiant que ce ne sera qu'une exception résident à L'intérieur de Throwable.

0
répondu Sidath Bhanuka Randeniya 2017-11-04 13:12:36

la question est un peu vague; demandez-vous "est-ce QU'on peut attraper Throwable ", ou "est-ce QU'on peut attraper un Throwable et ne rien faire"? Beaucoup de gens ici ont répondu à cette dernière, mais c'est une question secondaire; 99% du temps, vous ne devriez pas "consommer" ou rejeter l'exception, si vous attrapez Throwable ou IOException ou autre.

si vous propagez l'exception, la réponse (comme la réponse à tant de questions) est "cela dépend". Cela dépend de ce que vous faites avec l'exception-pourquoi vous l'attrapez.

un bon exemple de pourquoi vous voulez attraper Throwable est de fournir une sorte de nettoyage s'il y a une erreur. Par exemple, dans JDBC, si une erreur se produit au cours d'une transaction, vous voudriez faire revenir en arrière la transaction:

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

noter que l'exception n'est pas écartée, mais propagée.

mais comme une politique générale, attraper Throwable parce que vous n'avez pas de raison, et sont trop paresseux pour voir quelles exceptions sont par est médiocre et une mauvaise idée.

0
répondu Garret Wilson 2018-05-22 16:41:42

en général, vous voulez éviter d'attraper Error s mais je peux penser à (au moins) deux cas spécifiques où il est approprié de le faire:

  • Vous voulez arrêter l'application en réponse à des erreurs, en particulier AssertionError qui est sans danger.
  • est-ce que vous implémentez un mécanisme de mise en commun de threads similaire à ExecutorService.soumettre () qui vous oblige à transmettre les exceptions retour à l'utilisateur pour qu'ils puissent le gérer.
0
répondu Gili 2018-07-27 03:21:35