Est-il une préférence pour les sous blocs try/catch?
L'une des choses qui toujours me dérange à propos de l'utilisation des Lecteurs et des Flux en Java, c'est que le 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
que jeter IOExceptions? Il semble donc probable pour moi que, si la lecture échoue, près échouera pour la même raison.
- Le pire, c'est effectivement que la méthode close() peut lever une exception. Si une exception se produit, alors quoi d'autre pourriez-vous faire d'autre que de fermer le stream? Et puis de la fermeture de il jette une autre exception, de sorte que vous devrait fermer le flux de données, ce qui... je n'aime pas Java pour ces bêtises.
- Qu'advient-il si l'utilisateur travaille sur un ensemble de flux et l'on ne parvient pas à fermer? Cela pourrait signifier que tous les autres cours d'eau sont dans un état inutilisable et doit être testé. S'il est ignoré, alors qu'ils pourraient être dans un état inutilisable et l'utilisateur continue à faire le travail et ne pas être en mesure de sauver.
- Mon point est que vous ne pouvez pas faire quelque chose, mais de le fermer lorsqu'une exception est levée, alors pourquoi jeter LORS de la fermeture? L'OMI de clôture ne doit pas échouer, parce que vous ne pouvez pas faire quoi que ce soit et vous ne pouvez pas en sortir. Le flux est mauvaise après la clôture, a échoué ou non. Dans .NET, Close() ne pas jeter.
- Si vous utilisez un seul flux est valide. Toutefois, lorsque plusieurs flux sont en jeu, il est une excellente occasion pour déclencher un test de cohérence des autres cours d'eau afin de déterminer si l'intervention de l'utilisateur est requise.
- Je n'ai jamais vu de code qui fait que, bien que. La plupart soit à l'arrêt lorsque l'un flux échoue (car vous ne pouvez pas continuer, même si les autres filières sont très bien), ou ils continuent et se faire une exception par rapport aux autres cours d'eau quand elles sont mauvaises.
Vous devez vous connecter pour publier un commentaire.
Je serais toujours aller pour le premier exemple.
Si proches étaient à lever 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.
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, le
finally
bloc s'exécute. So far So good. Mais que faire si lefr.close()
provoque alors une autre exception à être jetés? Ce sera "trump" la première exception (un peu comme mettrereturn
dans unfinally
bloc) 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:
où cette méthode utilitaire ne fonctionne tout simplement:
Je préfère la deuxième. Pourquoi? Si les deux
read()
etclose()
lancer des exceptions, l'un d'eux pourrait être perdu. Dans la première construction, à l'exception declose()
remplace l'exception deread()
, tandis que dans le second, à l'exception declose()
est gérée séparément.De Java 7, la try-with-resources construire cela rend beaucoup plus simple. À lire sans se soucier des exceptions:
Avec la gestion des exceptions:
Un seul try-catch est nécessaire et toutes les exceptions peuvent être manipulées sans risque. Vous pouvez toujours ajouter une
finally
bloc si vous le souhaitez, mais il n'est pas nécessaire de fermer les ressources.Si les deux lire et près lancer une exception, l'exception de lire 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éré.
Si vous avez besoin de passer tous les générées exceptions, il peut être fait.
La différence, aussi loin que je peux voir, c'est qu'il y a des exceptions et des causes de jouer sur différents niveaux, et la
catch (Exception e)
obscurcit que. Le seul point à des niveaux multiples est à distinguer de vos exceptions, et ce que vous allez faire à leur sujet:
J'ai l'habitude de faire ce qui suit. Tout d'abord, de définir un modèle de la méthode en fonction de la classe de traiter avec le try/catch mess
Note le "en attente" exception -- cela prend en charge les cas où une exception levée lors de proximité serait masque une exception, nous pourrions vraiment se soucier.
Enfin essaie de fermer de l'extérieur de toute décorée de flux en premier, donc si vous aviez un BufferedWriter l'enveloppant d'un FileWriter, nous essayons de fermer la BuffereredWriter premier, et si cela échoue, essayez de fermer le FileWriter lui-même.
Vous pouvez utiliser la classe ci-dessus comme suit:
En utilisant cette approche, vous n'avez jamais à vous soucier de le try/catch/finally pour faire face à la fermeture des fichiers à nouveau.
Si c'est trop lourd pour votre utilisation, à moins penser à la suite de la try/catch et le "en attente" approche de la variable qu'il utilise.
La convention standard que j'utilise est que vous ne devez pas laisser les exceptions échapper à un bloc finally.
C'est parce que si une exception est déjà se propageant à l'exception de jeter le bloc finally l'emporte sur l'exception d'origine (et donc perdu).
Dans 99% des cas ce n'est pas ce que vous voulez que l'exception d'origine est probablement la source de votre problème (secondaire exceptions peuvent être des effets secondaires de la première, mais obscurcit votre capacité à trouver la source de l'exception d'origine et donc le vrai problème).
Sorte de base de votre code devrait ressembler à ceci:
2ème approche.
Sinon, je ne vois pas de vous attraper l'exception de la FileReader constructeur
http://java.sun.com/j2se/1.5.0/docs/api/java/io/FileReader.html#FileReader(java.lang.Chaîne de caractères)
public FileReader(String fileName)
throws FileNotFoundException
Donc, j'ai l'habitude le constructeur à l'intérieur du bloc try ainsi. le bloc finally vérifie si le lecteur n'est PAS null avant d'essayer de faire un close.
Le même schéma va pour la source de données, de Connexion, de Déclaration, ResultSet.
Parfois imbriqués try-catch n'est pas une préférence, pensez à ceci:
C'est probablement un mauvais exemple, mais il y a parfois, vous aurez besoin imbriquée essayez-cactch.
J'aime l'approche par @Chris Marshall, mais je n'ai jamais aime voir les exceptions se avalé en silence. Je pense qu'il est préférable d'enregistrer des exceptions, surtout si vous êtes contiuing indépendamment.
J'ai toujours utiliser une classe utilitaire pour gérer ce genre de commune des exceptions, mais je ferais ce petit différent à sa réponse.
Je serais toujours utiliser un enregistreur (log4j pour moi) pour le journal des erreurs, etc.
Une légère modification à la méthode d'utilitaire:
Dans certains cas, un imbriquée Try-Catch est inévitable. Par exemple lors de la récupération d'erreur code lui-même pouvez jeter et d'exception. Mais afin d'améliorer la lisibilité du code, vous pouvez toujours extraire le bloc imbriqué dans une méthode qui lui est propre. Découvrez cette sur le blog pour plus d'exemples sur imbriquée Try-Catch-finally blocs.