2015-09-20 4 views
1

À de nombreux endroits, je reçois plusieurs exceptions cochés comme IOException, ParseException, JSONException, etc. je devais faire l'un des 2 choix -Lancer exception vérifiée vs Lancer un RuntimeException enveloppé

  1. Jetez la même exception par ajouter des lancers à la fin de la signature de la méthode. Enveloppez l'exception vérifiée dans une exception RuntimeException (ou une implémentation personnalisée), puis lancez-la afin que l'appelant n'ait pas besoin d'ajouter une clause throws partout et de vérifier les exceptions.

Dans le premier cas, je vais devoir mettre jette partout, mais mon client peut décider de ne pas mourir en attrapant le checkedException et continuer à travailler. Dans le second cas, cependant, RuntimeException peut réellement forcer le client à échouer, car généralement les gens n'attrapent pas Generic/RuntimeExceptions partout. L'utilisation de la 2ème approche facilite également l'utilisation de Java 8 lambdas qui ne fonctionne pas correctement avec les exceptions vérifiées.

Lequel des deux est préféré à un autre et pourquoi? Y a-t-il une pratique préférée à suivre?

+0

Je ne pense pas qu'il y ait une réponse * right *, mais si vous regardez Spring Framework, la tendance est d'encapsuler les exceptions vérifiées sous une exception d'exécution. Documentez via JavaDoc ou la clause throws ce qui pourrait être appelé si les clients veulent le gérer, ils le peuvent. – JustinKSU

+3

@wero c'est une très mauvaise pratique, car elle inclura des exceptions que vous ne lancez pas actuellement, mais le ferait si votre implémentation change, et devrait être gérée de manière spécifique. L'exemple évident est InterruptedException. –

+0

@wero pourquoi me considérez-vous comme un hypocrite? Voulez-vous simplement dire que vous n'êtes pas d'accord? Je ne suis pas hypocrite (sur ce point, au moins): je pratique ce que je préconise. –

Répondre

1

Il existe deux types d'exceptions: les exceptions qui peuvent être attendues pour un appel et les exceptions qui sont en principe inattendues (et que le code d'application ne peut probablement pas fonctionner de manière significative). Pour le premier type (par exemple IOException pour une opération de fichier), les exceptions vérifiées (avec 'throws' à la fin d'une signature de méthode) sont excellentes. Pour la deuxième situation, je suis d'avis qu'il est bon d'envelopper une exception RuntimeException pour les raisons que vous énoncez (ne pas avoir à ajouter des lancers partout). Tous les logiciels doivent être prêts à attraper RuntimeExceptions au niveau supérieur en tant que «dernière ligne de défense», ou ils acceptent qu'une exception RuntimeException termine le programme (ce qui est souvent acceptable par exemple pour les applications en ligne de commande).

Un exemple pour la seconde situation est qu'un fichier de configuration nécessaire est manquant. Je voudrais réécrire cette exception IOException comme RuntimeException. Par ailleurs, il existe une troisième méthode souvent utilisée: lancer une exception spécifique à une application. Par exemple, cette exception pourrait s'appeler 'MyConfigurationException'. Je pense que ce n'est utile que si une application peut attraper cette exception et la gérer intelligemment.

0

(1) Jeter la même exception vérifiée en ajoutant jette à la fin de la signature de la méthode:

Utiliser ce si l'appelant peut se remettre de l'exception ou du moins a de prendre une décision/les progrès en fonction de cette

(2) Enveloppez l'exception vérifiée dans un RuntimeException (ou une implémentation personnalisée):

utiliser si l'appelant ne peut pas récupérer (la plupart des exceptions à Spring/Hibernate cadres suivent ce modèle)

0

Il y a une troisième option, qui consiste à lancer la même vérification Exception mais "adoucis".CheckedExceptions sont appliquées uniquement au moment de la compilation, et en envoyant votre exception à un Throwable, vous pouvez le lancer en toute sécurité sans que le compilateur ne se plaint. Voici un exemple d'implémentation (disponible dans une bibliothèque cyclops-functions je contribue à - ou vous pouvez copier et coller :))

MISE À JOUR classe simplifié ExceptionSoftener selon le commentaire de Andy Turner.

public class ExceptionSoftener { 


    public static <T extends Throwable> T softenedException(final T e) { 
     uncheck(e); 
     return e; //never reached. 
    } 

    private static <T extends Throwable> void uncheck(Throwable throwable) throws T { 
     throw (T) throwable; 

    } 

} 

    public void methodThrowsIOException(){  
     throw ExceptionSoftener.softenedException(new IOException("checked exception, but no declaration required!")); 
    } 
+1

La classe 'Thrower' est-elle nécessaire ici: pourquoi ne pas simplement déclarer' private static void uncheck (Throwable t) lance T' dans 'ExceptionSoftener', et invoque' ExceptionSoftener. uncheck (e) '? –

+0

Bonne idée, j'ai modifié le code pour refléter cela. –

+0

J'aurais pensé que ce serait une bonne idée de faire le type de retour de 'throwSoftenedException'' RuntimeException' au lieu de 'void', afin que vous puissiez utiliser' throw ExceptionSoftener.throwSoftenedException (...) 'pour indiquer à le compilateur que l'exécution s'arrêtera sur cette ligne. –