45 votes

Est-ce qu'un bloc finally sans bloc bloque un anti-motif java?

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 ceci:

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!")

63voto

dsimcha Points 32831

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.

26voto

Logan Capaldo Points 22145

Je pense que le vrai "anti-motif" ici fait quelque chose dans un bloc finally qui peut lancer, ne pas avoir un piège.

16voto

OscarRyz Points 82553

Pas du tout.

Ce qui ne va pas, c'est le code à l'intérieur de la finale.

Rappelez-vous que finalement, il sera toujours exécuté et qu'il est risqué (comme vous venez de le voir) de mettre quelque chose qui pourrait jeter une exception.

10voto

Bryan Kyle Points 5931

Il n'y a absolument rien de mal à essayer avec un finalement et pas de piège. Considérer ce qui suit:

 InputStream in = null;
try {
    in = new FileInputStream("file.txt");
    // Do something that causes an IOException to be thrown
} finally {
    if (in != null) {
         try {
             in.close();
         } catch (IOException e) {
             // Nothing we can do.
         }
    }
}
 

Si une exception est levée et que ce code ne sait pas comment le gérer, l'exception doit faire remonter la pile d'appels vers l'appelant. Dans ce cas, nous souhaitons toujours nettoyer le flux, je pense donc qu'il est parfaitement logique de disposer d'un bloc try sans prise.

5voto

Ravi Wallau Points 5012

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:


OutputStream os = null;
OutputStreamWriter wos = null;
try { 
   os = new FileOutputStream(...);
   wos = new OutputStreamWriter(os);
   // Lots of code

   wos.flush();
   os.flush();
finally {
   IOUtils.closeQuietly(wos);
   IOUtils.closeQuietly(os);
}

J'aime le faire de cette façon pour les raisons suivantes:

  • Il n'est pas complètement sûr d'ignorer une exception lors de la fermeture d'un fichier, si il y a des octets qui n'ont pas été écrites sur le fichier pour le moment, le fichier peut ne pas être dans l'état de l'appelant pourrait s'attendre;
  • Donc, si une exception est levée lors de la méthode flush (), il sera propagée à l'appelant, mais j'ai encore assurez-vous que tous les fichiers sont fermés. La méthode IOUtils.closeQuietly(...) est moins verbeux alors le correspondant de try ... catch ... m'ignorer bloc;
  • Si vous utilisez plusieurs flux de sortie de l'ordre de la méthode flush() est important. Les cours d'eau qui ont été créées par le passage des autres cours d'eau comme les constructeurs devraient être vidées en premier. La même chose est valable pour la méthode close (), mais la méthode flush() est de plus en plus clair à mon avis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X