ejemplo java stringreader

java - ejemplo - ¿Debo cerrar un StringReader?



stringreader c# (5)

Aunque estrictamente no es necesario, porque StringReader solo se aferra a una Cadena, como cuestión de buena forma, siempre es una buena idea cerrar todos los Lectores de todos modos. Hoy su código podría estar usando un StringReader, pero si lo cambiara a otro Reader que realmente necesita cerrarse, su código al final sería incorrecto, mientras que su cierre sería correcto.

Utilizo un StringReader para convertir una cadena en algo que puedo cargar en un servidor SFTP (toma una corriente). ¿Hay algún punto en cerrar ese StringReader después? Por lo que puedo ver en la fuente, solo establece la cadena en null ...

Simplemente podría hacerlo, pero como el método de cierre está marcado como lanzar una IOException y todo lo que tengo que envolver en un retén de prueba, el código simplemente parece mucho más horrible de lo que quizás deba ser.


Hace más que eso. Si puedo citar el 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. */

Así que sí, deberías cerrar ese lector. No por el bien de los recursos, sino por el buen estilo y los programadores que pueden seguirlo. No sabes a dónde se pasará esta instancia y qué intentará hacer otra persona con ella. Algún día, también puede elegir cambiar la interfaz y aceptar cualquier implementación de Reader, en cuyo caso podría tratar con un Reader que requiera una llamada para cerrar () y liberar recursos.

Por lo tanto, es un buen estilo evitar el uso posterior (posiblemente incorrecto) de esta instancia una vez que haya terminado con ella. Y como no duele, solo evitará posibles errores en el futuro.

Edición: ya que dice que su método close () está declarando una excepción que podría lanzar, diría que debe llamar a close () ya que StringReader.close () no lanza una excepción. Sin embargo, Reader.close () hace. Por lo tanto, ya permite otras implementaciones de Reader y, por lo tanto, debe cerrarla, ya que no puede saber qué implementaciones de Reader eventualmente obtendrá. Si estamos hablando de tres líneas de código que nunca salen de ese alcance, declare su variable StringReader y cierre la llamada de todos modos (en ese caso, sin el manejo de excepciones).


No necesita capturar una excepción si su variable tiene el tipo StringReader , en lugar de Reader , ya que StringReader#close() no lanza una excepción: solo Reader#close() sí lo hace. Por lo tanto, puede usar try-with-resources para cerrar automáticamente el lector, sin necesidad de tener una plantilla para manejar las excepciones que no ocurrirán. Reader#close() lanzar IOException significa que los subtipos pueden lanzar este tipo de excepción, no que deban hacerlo . Este es uno de los casos raros en los que desea declarar una variable con un subtipo, no el supertipo; ¿Ver uso de interfaz o tipo para la definición de variable en java? para más.

Por lo tanto, sugeriría lo siguiente, que solo requiere un nivel de anidación, que es par para los recursos:

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

Sin embargo, hay poco valor en cerrar un StringReader , ya que no contiene un recurso externo (solo memoria administrada por Java, no un identificador de archivo o memoria nativa, por ejemplo), por lo que está bien omitirlo, aunque recomiendo una comentar por qué esto es seguro, ya que de lo contrario no es sorprendente cerrar un lector. Como se puede observar, close() simplemente anula el campo, según la fuente JDK 8: StringReader.java:198 . Si desea evitar el anidamiento y el cierre, puede escribir esto:

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

... o (usando un tipo más general para la variable):

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

La prueba normal con recursos funciona aquí porque StringReader#close() anula Reader#close() y afortunadamente declara que no lanza IOException .

Tenga en cuenta que este no es el caso de String Writer : StringWriter#close() declara que lanza IOException , a pesar de ser un nop. Esto es presumiblemente para compatibilidad hacia adelante, por lo que podría lanzar una excepción en una implementación futura, aunque esto es poco probable. Ver mi respuesta a ¿No cerrar un guionista causará una fuga? .

En tal caso (si el método no produce una excepción, pero la interfaz indica que podría hacerlo), la forma correcta de escribir esto, a la que probablemente alude, es:

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); } }

Este nivel de repetición es necesario porque no puede limitarse al bloqueo de prueba general, ya que, de lo contrario, podría tragarse accidentalmente una IOException del cuerpo de su código. Incluso si no hay ninguno actualmente, algunos podrían agregarse en el futuro y querría que el compilador lo advierta. Tenga en cuenta también que AssertionError , que documenta el comportamiento actual, también enmascararía una excepción lanzada por el cuerpo de la instrucción try, aunque esto nunca debería ocurrir. Si esta fuera la alternativa, claramente estaría mejor omitiendo el close() y comentando por qué.

Esta respuesta depende del hecho de que estás creando el StringReader ti mismo; por supuesto, si recibe un Reader de otro lugar (como el tipo de retorno de una fábrica, por ejemplo), entonces necesita cerrarlo y manejar la posible excepción, ya que no sabe qué recursos puede tener, y puede lanzar una excepción.


Si cierra la corriente y libera cualquier recurso del sistema asociado a ella. Una vez que se haya cerrado la transmisión, las invocaciones adicionales de lectura (), ready (), mark () o reset () lanzarán una IOException. Cerrar una secuencia previamente cerrada no tiene efecto. Especificado por: close in interface Closeable Especificado por: close en clase Reader


Si sabe que está tratando con un StringReader que va a tirar, no veo ninguna razón para cerrarlo. No puedo imaginar ninguna razón por la que mantendrías una referencia a ella después de cerrarla, por lo que no hay un beneficio real para que la cadena se establezca en null para la recolección de basura. Si estaba creando un método que toma un Reader entonces podría tener sentido cerrarlo ya que no conoce el tipo subyacente.