J'ai été récemment surpris de constater qu'il est possible d'avoir une instruction return dans un bloc finally en Java.
Il semble que beaucoup de gens pensent que c'est une mauvaise chose à faire comme décrit dans « Ne pas revenir dans une clause enfin ». En grattant un peu plus profondément, j'ai également trouvé que `` le retour de Java n'est pas toujours '', ce qui montre des exemples assez horribles d'autres types de contrôle de flux dans les blocs finally.
Donc, ma question est la suivante: quelqu'un peut-il me donner un exemple où une instruction return (ou un autre contrôle de flux) dans un bloc finally produit un code meilleur / plus lisible?
la source
Il y a des années, j'ai eu vraiment du mal à trouver un bogue causé par cela. Le code était quelque chose comme:
Ce qui s'est passé, c'est que l'exception a été levée dans un autre code. Il était capturé et consigné et renvoyé dans la
somethingThatThrewAnException()
méthode. Mais l'exception n'était pas propagée par le passéproblemMethod()
. Après un LONG temps à regarder cela, nous l'avons finalement retracé jusqu'à la méthode de retour. La méthode de retour dans le bloc finally empêchait essentiellement l'exception qui s'est produite dans le bloc try de se propager même si elle n'était pas interceptée.Comme d'autres l'ont dit, bien qu'il soit légal de revenir d'un bloc finally selon la spécification Java, c'est une mauvaise chose et ne devrait pas être fait.
la source
javac vous avertira de retour dans enfin si vous utilisez le -Xlint: finally. À l'origine, javac n'émettait aucun avertissement - si quelque chose ne va pas avec le code, il ne devrait pas être compilé. Malheureusement, la rétrocompatibilité signifie qu'une sottise ingénieuse imprévue ne peut être interdite.
Des exceptions peuvent être lancées à partir de blocs finally, mais dans ce cas, le comportement affiché est presque certainement ce que vous voulez.
la source
L'ajout de structures de contrôle et de retours aux blocs finally {} ne sont qu'un autre exemple d'abus «juste parce que vous pouvez» qui sont dispersés dans pratiquement tous les langages de développement. Jason avait raison de suggérer que cela pourrait facilement devenir un cauchemar de maintenance - les arguments contre les retours anticipés des fonctions s'appliquent davantage à ce cas de «retours tardifs».
Enfin, les blocs existent dans un seul but, pour vous permettre de ranger complètement après vous-même, peu importe ce qui s'est passé dans tout le code précédent. Principalement, il s'agit de fermer / libérer des pointeurs de fichiers, des connexions à la base de données, etc., bien que je puisse le voir s'étirer pour dire l'ajout d'un audit sur mesure.
Tout ce qui affecte le retour de la fonction doit se trouver dans le bloc try {}. Même si vous aviez une méthode par laquelle vous avez vérifié un état externe, effectué une opération qui prend du temps, puis vérifié à nouveau cet état au cas où il deviendrait invalide, vous voudriez toujours la deuxième vérification à l'intérieur du try {} - si elle était finalement à l'intérieur {} et l'opération longue a échoué, vous vérifieriez alors cet état une seconde fois inutilement.
la source
Un test Groovy simple:
Production:
Question:
Un point intéressant pour moi était de voir comment Groovy gère les retours implicites. Dans Groovy, il est possible de "retourner" à partir d'une méthode en laissant simplement une valeur à la fin (sans retour). Que pensez-vous qu'il se passe, si vous décommentez la ligne runningThreads.remove (..) dans l'instruction finally - est-ce que cela écrasera la valeur de retour normale ("OK") et couvrira l'exception?!
la source
Revenir de l'intérieur d'un
finally
bloc entraîneraexceptions
la perte.Une instruction return dans un bloc finally provoquera la suppression de toute exception qui pourrait être levée dans le bloc try ou catch.
Selon la spécification du langage Java:
Remarque: selon JLS 14.17 - une instruction de retour se termine toujours brusquement.
la source