Votre code qui appelle InputStream.close()
o OutputStream.close()
est un code de haut niveau qui délègue au niveau inférieur InputStream
o OutputStream
pour effectuer des calculs de haut niveau.
Si l'on veut lancer une exception
Vous n'avez que 3 choix sur ce que vous devez faire.
- Attrapez et avalez l'exception, en la rejetant.
- Laissez-le se propager vers le haut.
- Attrapez l'exception, et lancez un autre type d'exception. Normalement, vous devriez utiliser une exception chaînée dans ce cas.
Les deux dernières options sont similaires dans la mesure où votre code lève une exception. Cette question est donc en fait un cas particulier de la question du Quand mon code doit-il lever une exception ? . Le site réponse correcte à cette question dans ce contexte, c'est : si, et seulement si, l'alternative est de ne pas remplir une condition de poste. de votre code ou pour maintenir un invariant de votre code . Les conditions de poste précisent ce que votre méthode est censée faire. Les invariants précisent les caractéristiques de la classe.
Vous devez donc vous demander si le close()
le fait de lancer une exception empêche votre méthode faisant ce qu'elle doit faire.
- Si cela n'empêche pas votre méthode de faire son travail, la bonne chose à faire est d'avaler l'exception. Malgré ce que beaucoup de gens vous diront.
- Si
close()
le lancer empêche votre méthode de faire son travail, et la méthode peut lancer IOException
vous ne pouvez rien faire, en laissant l'exception se propager vers le haut .
- Si
close()
empêche votre méthode de faire son travail, mais la méthode ne peut pas jeter IOException
vous devez attraper le IOException
et de la rejeter comme une classe d'exception différente, en enregistrant la IOException
comme la cause de l'exception levée.
Je ne connais pas de circonstances dans lesquelles un InputStream.close()
Le fait de lancer une exception peut empêcher un calcul d'aboutir. Cet appel à close()
arrive naturellement après vous avez fini de lire les données qui vous intéressent.
Les flux de sortie, en revanche, peuvent mettre en mémoire tampon les données à écrire sur la destination de sortie, soit en interne (dans le code Java), soit à un niveau inférieur (dans le système d'exploitation). Vous ne pouvez donc pas être sûr que les opérations d'écriture vers un flux de sortie ont effectivement donné lieu à une sortie réelle jusqu'à ce que OutputStream.close()
est retourné avec succès ( sans en lançant une exception). Vous devez donc traiter une exception lancée par OutputStream.close()
comme un échec d'écriture.
Votre méthode est responsable du maintien de ses invariants. Parfois, cela nécessitera une opération de nettoyage ou de retour en arrière si close()
lance une exception. Vous devriez mettre le code pour cela dans un catch
o finally
pour la clause IOException
même si vous souhaitez que l'exception se propage vers le haut. Si vous utilisez une clause catch et que vous voulez la propager, vous devrez la relancer.
S'il faut enregistrer l'exception
Certaines personnes vous conseille d'enregistrer l'exception . C'est presque toujours un mauvais conseil. Les messages de journalisation font partie de l'interface utilisateur de votre programme. Fondamentalement, vous devez toujours vous demander s'il faut journaliser tout ce qui est pas du tout, car un verbiage inutile peut distraire et embrouiller les utilisateurs qui lisent votre fichier journal (les "utilisateurs" incluent les administrateurs système). Chaque message enregistré doit avoir un but utile. Chacun doit fournir des informations qui aident l'utilisateur à prendre des décisions .
En signalant spécifiquement que close()
échoué est rarement utile. Comment peut-elle aider un utilisateur à prendre une décision ? Si l'exception n'a pas empêché votre méthode de faire son travail, il n'y a pas de problème et aucune action de l'utilisateur n'est nécessaire. Si votre programme n'a pas réussi à close()
le cours d'eau, et que es un problème, que peut faire l'utilisateur pour l'aider ?
Le code de bas niveau n'est généralement pas responsable de la journalisation. Il effectue plutôt des opérations abstraites, signalant les échecs aux parties de niveau supérieur de votre programme en lançant des exceptions. Le code qui ferme un flux est typiquement de bas niveau, donc le code qui détecte que la fermeture d'un flux est une exception. close()
est trop bas pour faire de la journalisation.
Le fait spécifique que close()
échoué est rarement utile. Ce qui peut être utile, c'est de savoir que l'opération abstraite que votre méthode est censée exécuter a échoué. Pour ce faire, le code de niveau supérieur doit attraper toutes les exceptions attendues et signaler que l'opération a échoué, plutôt que de demander à votre méthode de signaler précisément que "close failed".