Dois-je fermer un StringReader?

j'utilise un StringReader pour transformer une chaîne en quelque chose que je peux télécharger sur un serveur SFTP (il faut un flux). Il y a tout point, en conclusion, que StringReader la suite? Pour autant que je puisse voir dans la source, il ne fait que mettre la chaîne à null...

seulement je pouvais le faire, mais depuis la fin de la méthode est marqué que de lancer un IOException et tout ce que j'ai pour l'envelopper dans une prise d'essai et le code finit juste par sembler beaucoup plus horrible que ce qu'il a peut-être besoin d'être.

18
demandé sur Jonathan Leffler 2011-05-25 13:08:35

5 réponses

Si vous savez que vous avez affaire à un StringReader que vous serez jeter, je ne vois pas de raison de le fermer. Je ne vois aucune raison pour que vous ayez une référence après avoir fermé, donc il n'y a aucun avantage à mettre la chaîne à null pour la collecte des ordures. Si vous créez une méthode qui prend un Reader alors il pourrait être logique de le fermer puisque vous ne connaissez pas le type sous-jacent.

13
répondu WhiteFang34 2011-05-25 09:19:26

bien que ce ne soit pas strictement nécessaire, parce que StringReader ne tient sur une corde, comme une question de bonne forme c'est toujours une bonne idée de fermer tous les lecteurs de toute façon. Aujourd'hui, votre code peut utiliser un lecteur StringReader mais si vous le changez pour un autre lecteur qui a vraiment besoin d'être fermé, votre code w/out the close sera erroné alors que votre w/ close sera parfait.

4
répondu mP. 2011-05-25 22:41:36

Il fait plus que cela. Si je peux citer le JavaDoc:

/**
 * Closes the stream and releases any system resources associated with
 * it. Once the stream has been closed, further read(),
 * ready(), mark(), or reset() invocations will throw an IOException.
 * Closing a previously closed stream has no effect.
 */

donc oui, vous devriez fermer ce lecteur. Pas pour les ressources, mais pour le bon style et les programmeurs qui peuvent vous suivre. Vous ne savez pas où cette instance sera transmise et ce que quelqu'un d'autre essaiera de faire avec. Un jour, vous pourriez également choisir de changer l'interface et d'accepter n'importe quelle implémentation de lecteur, auquel cas vous pourriez traiter avec un lecteur qui nécessite un appel à fermer () pour libérer ressources.

C'est donc un bon style pour empêcher l'utilisation ultérieure (éventuellement erronée) de cette instance une fois que vous en avez fini avec elle. Et comme ça ne fait pas de mal, ça empêchera seulement les erreurs possibles dans le futur.

Edit: Puisque vous dites, que votre méthode close () déclare une exception qu'elle pourrait jeter je dirais que vous besoin pour appeler close () depuis StringReader.close() ne renvoie pas une exception. Cependant, Le Lecteur.close () le fait. Si vous avez déjà autoriser d'autres implémentations de Reader et donc vous devez le fermer car vous ne pouvez pas savoir quelles implémentations de Reader vous obtiendrez éventuellement. Si nous parlons de trois lignes de code qui ne quittent jamais cette portée, déclarez votre variable StringReader et appelez close de toute façon (dans ce cas sans manipulation d'exception).

3
répondu Stephan 2011-05-25 10:05:09

Vous n'avez pas besoin d'attraper une exception si votre variable a le type StringReader au lieu de Reader, car StringReader#close() ne lance pas d'exception: seulement Reader#close() ne. Ainsi, vous pouvez utiliser try-with-resources pour fermer automatiquement le lecteur, sans avoir besoin d'avoir boilerplate pour gérer les exceptions qui ne se produiront pas. Reader#close() lancer IOException signifie sous-types jeter ce type d'exception, non pas qu'ils . C'est l'un des rares cas où vous souhaitez déclarer une variable avec un type, pas le supertype; voir utiliser l'interface ou le type pour la définition des variables en java? pour plus d'.

ainsi, je suggère ce qui suit, qui nécessite juste un niveau de nidification, qui est égal pour les ressources:

try (StringReader reader = new StringReader(string)) {
    // Do something with reader.
}

cependant, il y a peu de valeur à fermer un StringReader, puisqu'il ne contient pas de ressource externe (seulement de la mémoire gérée par Java, pas un fichier la poignée ou le natif de mémoire, par exemple), il est donc très bien pour l'omettre, bien que je recommanderais un commentaire en indiquant pourquoi est-ce sûr, car sinon pas de la fermeture d'un lecteur est surprenant. Comme vous le notez, close() null sur le terrain, par le JDK 8 source: StringReader.java: 198. Si vous voulez éviter le nichage et fermer, vous pouvez juste écrire ceci:

// Don't need to close StringReader, since no external resource.
StringReader reader = new StringReader(string);
// Do something with reader.

...ou (à l'aide de plus général type de variable):

// Don't need to close StringReader, since no external resource.
Reader reader = new StringReader(string);
// Do something with reader.

normal try-with-resources fonctionne ici parce que StringReader#close() remplace Reader#close() et heureusement affirme ne pas jeter IOException.

attention que c'est le cas pour la Chaîne Ecrivain:StringWriter#close() déclarez qu'il lance IOException, en dépit d'être un nop! Il s'agit probablement de compatibilité prospective, de sorte qu'il pourrait jeter une exception dans une future mise en œuvre, bien que cela soit peu probable. Voir ma réponse pour ne Sera pas de la fermeture d'un stringwriter cause une fuite?.

dans un tel cas (si la méthode ne lance pas une exception, mais l'interface a déclaré qu'elle pourrait), la manière stricte d'écrire ceci, à laquelle vous faites sans doute allusion, est:

Reader reader = new StringReader(string);
try {
    // Do something with reader, which may or may not throw IOException.
} finally {
    try {
        reader.close();
    } catch (IOException e) {
        throw new AssertionError("StringReader#close() cannot throw IOException", e);
    }
}

ce niveau de boilerplate est nécessaire parce que vous ne pouvez pas simplement mettre une prise sur le bloc d'essai global, sinon vous pourriez accidentellement avaler un IOException jetés par le corps de votre code. Même si il n'y a pas actuellement, certains pourraient être ajouté dans le futur et vous voudriez être averti de cela par le compilateur. Notez également que l' AssertionError, qui documente le comportement actuel, masquerait aussi une exception lancée par le corps de la déclaration try, bien que cela ne devrait jamais se produire. Si c'était l'alternative, vous feriez mieux d'omettre le close() et commentant pourquoi.

cette réponse dépend du fait que vous créez le StringReader toi-même; bien sûr, si vous recevez un Reader de quelque part ailleurs (comme le type de retour d'une usine, par exemple), alors vous devez la fermer et gérer l'exception possible, car vous ne savez pas quelles ressources il peut contenir, et il peut jeter une exception.

0
répondu Nils von Barth 2017-05-23 12:02:12

si vous fermez le flux et relâchez toutes les ressources système qui y sont associées. Une fois le flux fermé, d'autres invocations read(), ready(), mark(), ou reset() lanceront une IOException. La fermeture d'un cours d'eau fermé n'a aucun effet. Spécifié par: à proximité de l'interface Fermer Spécifié par: fermer dans le lecteur de classe

-1
répondu prasad.gai 2011-05-25 09:22:26