41 votes

Existe-t-il une préférence pour les blocs try / catch imbriqués?

L'une des choses qui toujours me dérange à propos de l'utilisation des Lecteurs et des Flux en Java, c'est que l' close() méthode peut lever une exception. Depuis c'est une bonne idée de mettre la méthode close dans un bloc finally, qui nécessite un peu d'une situation délicate. J'ai l'habitude d'utiliser cette construction:

FileReader fr = new FileReader("SomeFile.txt");
try {
    try {
        fr.read();
    } finally {
        fr.close();
    }
} catch(Exception e) {
    // Do exception handling
}

Mais j'ai aussi vu cette construction:

FileReader fr = new FileReader("SomeFile.txt");
try {
    fr.read() 
} catch (Exception e) {
    // Do exception handling
} finally {
    try {
        fr.close();
    } catch (Exception e) {
        // Do exception handling
    }
}

Je préfère la première construction, car il n'y a qu'un seul bloc catch et il me semble plus élégant. Est-il une raison pour lui préfère la deuxième ou une autre construction?

Mise à JOUR: y Aurait-il une différence si je l'ai fait remarquer que les deux read et close seulement jeter IOExceptions? Il semble donc probable pour moi que, si la lecture échoue, près échouera pour la même raison.

26voto

oxbow_lakes Points 70013

J'ai peur il y a un gros problème avec le premier exemple, qui est que si une exception se produit après la lecture, l' finally bloc s'exécute. So far So good. Mais que faire si l' fr.close() provoque alors une autre exception à être jetés? Ce sera "trump" la première exception (un peu comme mettre des return en finally de l'îlot) et vous perdrez toutes les informations au sujet de ce qui s'est réellement à l'origine du problème pour commencer.

Votre bloc finally doit utiliser:

IOUtil.closeSilently(fr);

d'où cette méthode utilitaire ne fonctionne tout simplement:

public static void closeSilently(Closeable c) {
    try { c.close(); } catch (Exception e) {} 
}

7voto

Tom Hawtin - tackline Points 82671

Je serais toujours aller pour le premier exemple.

Si fermer pour lancer une exception (en pratique cela ne se produira jamais pour un FileReader), ne serait pas le moyen standard de manipulation pour lancer une exception appropriée à l'appelant? La proximité exception presque certainement l'emporte sur tout problème que vous aviez à l'aide de la ressource. La deuxième méthode est sans doute plus approprié si votre idée de la gestion des exceptions est l'appel Système.err.println.

Il y a une question de savoir dans quelle mesure les exceptions doivent être jetés. ThreadDeath doit toujours être relancés, mais toute exception au sein de définitivement arrêter. De la même façon Erreur à ne jeter plus loin que les RuntimeException et RuntimeException plus loin que checked exceptions. Si tu voulais vraiment vous pourriez écrire du code pour suivre ces règles, et puis abstrait avec la "exécuter autour de" l'idiome.

3voto

Michael Myers Points 82361

Je préfère le second. Pourquoi? Si à la fois read () et close () lèvent des exceptions, l'une d'entre elles pourrait être perdue. Dans la première construction, l'exception de close () remplace l'exception de read (), tandis que dans la seconde, l'exception de close () est traitée séparément.

EDIT: je tape trop lentement.

2voto

McDowell Points 62645

Si à la fois lire et à proximité de lever une exception, l'exception de lecture sera caché dans l'option 1. Donc, la deuxième option n'est plus d'erreur de manipulation.

Cependant, dans la plupart des cas, la première option sera toujours préférable.

  1. Dans de nombreux cas, vous ne pouvez pas gérer les exceptions dans la méthode qu'ils ont généré, mais vous devez toujours encapsuler le flux de manutention à l'intérieur de cette opération.
  2. Essayez d'ajouter un écrivain pour le code et de voir comment verbose la deuxième approche est.

Si vous avez besoin de passer tous les générées exceptions, il peut être fait.

1voto

Steve B. Points 23227

La différence, à ce que je sache, est qu’il existe différentes exceptions et causes à différents niveaux, et

catch (Exception e)

obscurcit cela. Le seul point des multiples niveaux est de distinguer vos exceptions et ce que vous allez faire à leur propos:

 try
{
  try{
   ...
  }
   catch(IOException e)
  {
  ..
  }
}
catch(Exception e)
{
  // we could read, but now something else is broken 
  ...
}
 

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