Existe-t-il une manière élégante de gérer les exceptions qui sont lancées en finally
bloc?
Par exemple:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
Comment éviter le try
/ catch
dans le finally
bloc?
Resource
=>Closeable
?J'utilise généralement l'une des
closeQuietly
méthodes suivantesorg.apache.commons.io.IOUtils
:la source
Si vous utilisez Java 7 et
resource
implémentezAutoClosable
, vous pouvez le faire (en utilisant InputStream comme exemple):la source
Sans doute un peu exagéré, mais peut-être utile si vous laissez les exceptions bouillonner et que vous ne pouvez rien enregistrer à partir de votre méthode (par exemple, parce que c'est une bibliothèque et que vous préférez laisser le code appelant gérer les exceptions et la journalisation):
MISE À JOUR: J'ai examiné cela un peu plus et j'ai trouvé un excellent article de blog de quelqu'un qui a clairement pensé à cela plus que moi: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html Il va encore plus loin et combine les deux exceptions en une seule, ce que je pourrais voir utile dans certains cas.
la source
ignore
exceptionÀ partir de Java 7, vous n'avez plus besoin de fermer explicitement les ressources dans un bloc finally à la place, vous pouvez utiliser try la syntaxe -with-resources. L'instruction try-with-resources est une instruction try qui déclare une ou plusieurs ressources. Une ressource est un objet qui doit être fermé une fois que le programme en a terminé avec elle. L'instruction try-with-resources garantit que chaque ressource est fermée à la fin de l'instruction. Tout objet qui implémente java.lang.AutoCloseable, qui inclut tous les objets qui implémentent java.io.Closeable, peut être utilisé comme ressource.
Supposons le code suivant:
Si une exception se produit, la clôture méthode sera appelée sur chacune de ces trois ressources dans l'ordre inverse dans lequel elles ont été créées. Cela signifie que la méthode close serait appelée en premier pour ResultSetm puis pour Statement et à la fin pour l'objet Connection.
Il est également important de savoir que toutes les exceptions qui se produisent lorsque les méthodes close sont automatiquement appelées sont supprimées. Ces exceptions supprimées peuvent être récupérées par la méthode getsuppressed () définie dans la classe Throwable .
Source: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
la source
Ignorer les exceptions qui se produisent dans un bloc «finalement» est généralement une mauvaise idée à moins que l'on ne sache quelles seront ces exceptions et quelles conditions elles représenteront. Dans le
try/finally
modèle d'utilisation normal , letry
bloc place les choses dans un état auquel le code extérieur ne s'attendra pas, et lefinally
bloc restaure l'état de ces choses à ce que le code extérieur attend. Le code extérieur qui intercepte une exception s'attendra généralement à ce que, malgré l'exception, tout ait été restaurénormal
Etat. Par exemple, supposons que du code démarre une transaction et tente ensuite d'ajouter deux enregistrements; le bloc "finalement" effectue une opération "rollback si non validée". Un appelant peut être préparé à ce qu'une exception se produise lors de l'exécution de la deuxième opération "ajouter" et peut s'attendre à ce que s'il détecte une telle exception, la base de données sera dans l'état où elle était avant que l'une ou l'autre des opérations ne soit tentée. Si, cependant, une deuxième exception se produit pendant la restauration, de mauvaises choses peuvent se produire si l'appelant émet des hypothèses sur l'état de la base de données. L'échec de la restauration représente une crise majeure - une crise qui ne devrait pas être interceptée par le code en s'attendant à une simple exception «Échec d'ajout d'enregistrement».Mon inclination personnelle serait d'avoir une méthode enfin pour attraper les exceptions qui se produisent et les envelopper dans une "CleanupFailedException", en reconnaissant qu'un tel échec représente un problème majeur et qu'une telle exception ne doit pas être prise à la légère.
la source
Une solution, si les deux exceptions sont deux classes différentes
Mais parfois, vous ne pouvez pas éviter cette deuxième tentative. par exemple pour fermer un flux
la source
Pourquoi voulez-vous éviter le blocage supplémentaire? Puisque le bloc finally contient des opérations "normales" qui peuvent lever une exception ET que vous voulez que le bloc finally s'exécute complètement, vous DEVEZ intercepter les exceptions.
Si vous ne vous attendez pas à ce que le bloc finally lève une exception et que vous ne savez pas comment gérer l'exception de toute façon (vous ne feriez que vider la trace de la pile), laissez l'exception remonter la pile des appels (supprimez le try-catch du bloquer).
Si vous voulez réduire le typage, vous pouvez implémenter un bloc try-catch externe "global", qui capturera toutes les exceptions levées dans les blocs finally:
la source
Après beaucoup de réflexion, je trouve le code suivant le meilleur:
Ce code garantit ce qui suit:
la source
Si vous le pouvez, vous devez tester pour éviter la condition d'erreur pour commencer.
De plus, vous ne devriez probablement attraper que des exceptions dont vous pouvez récupérer, si vous ne pouvez pas récupérer, laissez-le se propager au niveau supérieur de votre programme. Si vous ne pouvez pas tester une condition d'erreur, vous devrez entourer votre code d'un bloc try catch comme vous l'avez déjà fait (même si je recommanderais toujours de détecter les erreurs spécifiques attendues).
la source
Vous pouvez refactoriser cela dans une autre méthode ...
la source
Je fais généralement ceci:
Justification: Si j'en ai fini avec la ressource et que le seul problème que j'ai est de la fermer, je ne peux pas y faire grand-chose. Cela n'a pas de sens non plus de tuer tout le fil si j'en ai fini avec la ressource de toute façon.
C'est l'un des cas où, du moins pour moi, il est prudent d'ignorer cette exception vérifiée.
À ce jour, je n'ai eu aucun problème à utiliser cet idiome.
la source
Travail accompli. Aucun test nul. Prise unique, comprend les exceptions d'acquisition et de libération. Bien sûr, vous pouvez utiliser l'idiome Execute Around et ne devez l'écrire qu'une seule fois pour chaque type de ressource.
la source
Passer
Resource
de la meilleure réponse àCloseable
Streams implémente
Closeable
Ainsi, vous pouvez réutiliser la méthode pour tous les fluxla source
J'ai rencontré une situation similaire où je ne pouvais pas utiliser try avec des ressources, mais je voulais également gérer l'exception provenant de la fermeture, pas seulement la journaliser et l'ignorer comme le fait le mécanisme closeQuietly. dans mon cas, je n'ai pas vraiment affaire à un flux de sortie, donc l'échec à la fermeture est plus intéressant qu'un simple flux.
la source