Est un bloc finally sans un bloc catch java anti-modèle?
J'ai juste eu un assez douloureux de dépannage de l'expérience dans la résolution de certains de code qui ressemble à ceci:
try {
doSomeStuff()
doMore()
} finally {
doSomeOtherStuff()
}
Le problème est difficile à résoudre car doSomeStuff() a lancé une exception, qui à leur tour causé doSomeOtherStuff() de lancer une exception. La deuxième exception (lancée par le bloc finally) a été levée à la hauteur de mon code, mais il n'a pas une poignée sur la première exception (jeté de doSomeStuff()), qui a été la véritable cause du problème.
Si le code avait dit ceci au lieu de cela, le problème aurait été évident:
try {
doSomeStuff()
doMore()
} catch (Exception e) {
log.error(e);
} finally {
doSomeOtherStuff()
}
Donc, ma question est: est-ce
Est un bloc finally utilisé sans aucun bloc catch bien connu java anti-modèle? (Il semble être un non-facilement-apparente sous-classe de la évidemment bien connu d'anti-modèle "Ne pas avaler des exceptions!")
- Voir aussi une question similaire sur try-finally sans prise en C# -- les mêmes arguments s'appliquent.
Vous devez vous connecter pour publier un commentaire.
En général, non, ce n'est pas un anti-modèle. Le point de enfin les blocs est de s'assurer que ça devient nettoyé si une exception est levée ou non. Le point de l'ensemble de la gestion des exceptions est que, si vous ne pouvez pas traiter avec elle, vous laissez bouillonner à quelqu'un qui peut, à travers les relativement propre extérieur de la bande de signalisation de la gestion des exceptions fournit. Si vous devez assurez-vous que les choses deviennent nettoyé si une exception est levée, mais ne peut pas gérer correctement l'exception dans le champ d'application actuel, alors c'est exactement la bonne chose à faire. Vous avez juste à être un peu plus prudent assurez-vous que votre bloc finally ne jette pas.
Je pense que le vrai "anti-modèle" ici est en train de faire quelque chose dans un
finally
bloc qui peut jeter, ne pas avoir un hic.Pas du tout.
Ce qui est mal, c'est le code à l'intérieur de la enfin.
Rappelez-vous que, finalement, sera toujours exécuté, et est un peu risqué ( comme vous l'avez vu ) pour mettre quelque chose qui peut lever une exception.
Il n'y a absolument rien de mal à essayer avec un enfin et pas de prise. Considérez les points suivants:
Si une exception est levée et ce code ne sais pas comment traiter avec elle, puis l'exception de la bulle en haut de la pile d'appel à l'appelant. Dans ce cas, nous voulons toujours nettoyer le stream donc je pense que cela a du sens d'avoir un bloc try sans crochet.
Je pense que c'est loin d'être un anti-modèle et est quelque chose que je fais très souvent quand il est critique de faire libérer les ressources obtenues au cours de l'exécution de la méthode.
Une chose que je fais lorsque vous traitez avec des descripteurs de fichiers (pour l'écriture) annule le flux avant de le fermer à l'aide de la IOUtils.closeQuietly méthode, qui permet de ne pas lancer des exceptions:
J'aime le faire de cette façon pour les raisons suivantes:
Je dirais un bloc try sans un bloc catch est un anti-pattern. En disant: "vous N'avez pas enfin sans un hic" est un sous-ensemble de "Ne pas essayer sans crochet".
- Je utiliser try/finally sous la forme suivante :
Je préfère cela à des try/catch/finally (+ imbriquée try/catch dans la enfin).
Je pense que c'est plus concis et je n'ai pas dupliquer le catch(Exception).
Ne pas le faire... vous venez de hid plus de bugs (enfin pas exactement caché... mais il est difficile de traiter avec eux. Lorsque vous prenez une Exception vous sont également attraper toute sorte de RuntimeException (comme NullPointer et erreur arrayindexoutofbounds).
En général, attraper les exceptions que vous avez à les attraper (checked exceptions) et de traiter avec les autres à la durée des tests. RuntimeExceptions sont conçus pour être utilisés pour les erreurs du développeur - programmeur et les erreurs sont des choses qui ne devrait pas arriver dans un programme débogué.
À mon avis, c'est plus le cas que
finally
avec uncatch
indiquer un certain genre de problème. Les ressources de l'idiome est très simple:En Java, vous pouvez avoir une exception à partir de pratiquement n'importe où. Souvent les acquérir jette un checked exception, la meilleure façon de gérer cela est de mettre un catch autour de la façon dont beaucoup. N'essayez pas certains hideux null vérification.
Si vous avez été va être vraiment anaux vous devriez noter qu'il existe implicite des priorités parmi les exceptions. Par exemple ThreadDeath doit tabasser, qu'il vient d'acquérir/utilisation/rejet. La manipulation de ces priorités correctement est inesthétique.
Par conséquent, abstrait votre ressource de la manipulation de loin avec l'Exécution Autour de l'idiome.
Try/finally est une façon de bien libérer des ressources. Le code dans le bloc finally ne devrait JAMAIS jeter car il ne doit intervenir que sur des ressources ou de l'état qui a été acquis AVANT l'entrée dans le bloc try.
En aparté, je pense que log4J est presque un anti-modèle.
SI VOUS VOULEZ INSPECTER l'EXÉCUTION d'UN PROGRAMME d'UTILISER UN BON OUTIL d'INSPECTION (c'est à dire un débogueur, IDE, ou dans un sens extrême, un octet de code weaver, mais NE METTEZ PAS de traces DANS TOUS les QUELQUES LIGNES!).
Dans les deux exemples vous présenter le premier semble correct. Le second comprend l'enregistreur de code et introduit un bug. Dans le deuxième exemple, la suppression d'une exception, si l'on est jeté par les deux premiers énoncés (c'est à dire que vous l'attraper et de l'enregistrer, mais ne pas le renvoyer. C'est quelque chose que je trouve très commun dans l'utilisation de log4j et est un réel problème de conception de l'application. Fondamentalement, avec votre changement que vous faites le programme d'échouer dans une manière qui sera très difficile pour le système à manipuler car vous fondamentalement marchons en avant, comme si vous n'avez jamais eu une exception (sorta comme VB de base on error resume next construire).
try-finally
peut vous aider à réduire le copier-coller le code dans le cas d'une méthode a plusieursreturn
consolidés. Considérons l'exemple suivant (Android Java):Si il n'y avait pas
finally
clause, vous pourriez avoir à écrirecursor.close()
deux fois: juste avantreturn false
et aussi après l'entourantif
clause.Je pense que essayez pas de l'attraper est anti-modèle. Utilisation de try/catch pour gérer exceptionnelle conditions (fichier des erreurs d'e /s, délai d'attente du socket, etc) n'est pas un anti-modèle.
Si vous utilisez try/finally pour le nettoyage, envisager l'utilisation de bloc à la place.