Java Language Piège - Lancer Throwable, Exception, Error ou RuntimeException


Exemple

Bien que la capture des Exception Throwable , Exception , Error et RuntimeException soit mauvaise, leur RuntimeException est encore pire.

Le problème de base est que lorsque votre application doit gérer des exceptions, la présence des exceptions de niveau supérieur rend difficile la distinction entre différentes conditions d'erreur. Par exemple

try {
    InputStream is = new FileInputStream(someFile);  // could throw IOException
    ...
    if (somethingBad) {
        throw new Exception();  // WRONG
    }
} catch (IOException ex) {
    System.err.println("cannot open ...");
} catch (Exception ex) {
    System.err.println("something bad happened");  // WRONG
}

Le problème est que parce que nous avons lancé une instance Exception , nous sommes obligés de l'attraper. Cependant, comme décrit dans un autre exemple, la détection des Exception est mauvaise. Dans ce cas, il devient difficile de faire la distinction entre le cas "attendu" d'une Exception déclenchée si somethingBad est true et le cas inattendu où nous interceptons une exception non vérifiée telle que NullPointerException .

Si l'exception de niveau supérieur est autorisée à se propager, nous rencontrons d'autres problèmes:

  • Nous devons maintenant nous souvenir de toutes les différentes raisons pour lesquelles nous avons lancé le plus haut niveau et les discriminer / gérer.
  • Dans le cas d' Exception et Throwable nous devons aussi ajouter ces exceptions à la throws clause de méthodes si nous voulons l'exception de se propager. Ceci est problématique, comme décrit ci-dessous.

En bref, ne jetez pas ces exceptions. Jetez une exception plus spécifique qui décrit plus précisément "l'événement exceptionnel" qui s'est produit. Si vous devez, définissez et utilisez une classe d'exception personnalisée.

Déclarer Throwable ou Exception dans les "lancers" d'une méthode est problématique.

Il est tentant de remplacer une longue liste d'exceptions lancées dans une méthode de throws clause avec Exception ou même `Throwable. C'est une mauvaise idée:

  1. Il force l'appelant à gérer (ou propager) les Exception .
  2. Nous ne pouvons plus compter sur le compilateur pour nous informer des exceptions vérifiées spécifiques à gérer.
  3. Manipuler correctement l' Exception est difficile. Il est difficile de savoir quelles exceptions réelles peuvent être interceptées et, si vous ne savez pas ce qui pourrait être capturé, il est difficile de savoir quelle stratégie de rétablissement est appropriée.
  4. Manipulation Throwable est encore plus difficile, car vous devez maintenant faire face à des défaillances potentielles qui ne devraient jamais être récupérées.

Ce conseil signifie que certains autres modèles doivent être évités. Par exemple:

try {
    doSomething();
} catch (Exception ex) {
    report(ex);
    throw ex;
}

Les tentatives ci-dessus tentent de consigner toutes les exceptions au fur et à mesure qu'elles passent, sans les traiter définitivement. Malheureusement, avant Java 7, le throw ex; La déclaration a amené le compilateur à penser que toute Exception pouvait être lancée. Cela pourrait vous obliger à déclarer la méthode englobante comme faisant throws Exception . A partir de Java 7, le compilateur sait que l'ensemble des exceptions qui pourraient être (re-lancées) est plus petit.