2010-02-15 11 views
7

En C#, casi siempre uso el patrón using cuando trabajo con objetos de transmisión. Por ejemplo:descarte de flujos en Java

 using (Stream stream = new MemoryStream()) 
     { 
      // do stuff 
     } 

Al utilizar el bloque de using, nos aseguramos de que disponen se llama en la corriente inmediatamente después de que el código se ejecuta Bock.

Sé que Java no tiene el equivalente de una palabra clave using, pero mi pregunta es que cuando se trabaja con un objeto como un FileOutputStream en Java, ¿necesitamos hacer algún mantenimiento para asegurarnos de que se elimine? Estaba mirando el ejemplo del código this, y noté que no hacen ninguno.

Me pregunto cuál es la mejor práctica para Java en el manejo de la eliminación de transmisiones, o si es lo suficientemente bueno como para permitir que el recolector de basura lo maneje.

Respuesta

6

general, usted tiene que hacer lo siguiente:

InputStream stream = null; 
try { 
    // IO stuff - create the stream and manipulate it 
} catch (IOException ex){ 
    // handle exception 
} finally { 
    try { 
    stream.close(); 
    } catch (IOException ex){} 
} 

Pero Apache commons-io proporciona IOUtils.closeQuietly(stream); que se pone en la cláusula finally para que sea un poco menos feo. Creo que habrá una mejora en eso en Java 7.

Actualización: Jon Skeet hizo un comentario muy útil, que el manejo real de la excepción rara vez es posible que ocurra en la clase en sí (a menos que sea simplemente para iniciar sesión eso, pero eso no es realmente manejarlo). Por lo tanto, será mejor que declare que su método arrojó esa excepción o la envuelve en una excepción personalizada (excepto para las operaciones simples y atómicas).

+0

¿Sabe si IOUtils.closeQuietly (transmisión) maneja una secuencia nula, de lo contrario podría arrojar NPE y causar el mismo problema (se come la excepción original). – dcp

+0

sí, 'IOUtils' comprueba nulo antes del cierre, por lo que no hay riesgo de NPE – Bozho

+0

genial, gracias por la respuesta. – dcp

5

No hay (lamentablemente) ningún equivalente de la declaración using en Java, aunque ha habido algunas ideas sobre la inclusión de algo similar en Java 7. (Creo que la última vez que miré estaban "fuera", pero me resulta difícil mantenerse al día con el estado de las funciones en Java 7.)

Baically necesita un try/finally:

InputStream stream = new FileInputStream(...); 
try { 
    ... 
} finally { 
    stream.close(); 
} 

Hay entonces el problema de qué hacer con el IOException en el caso de cierre () falla, y el problema de una excepción allí "sobrescribir" cualquier excepción lanzada por el cuerpo principal del código - al aunque este último también es un problema en .NET.

Guava hace que este un poco más fácil con la clase Closeables, con estáticas close y closeQuietly métodos que se ocupará de stream siendo nula (en el caso en el que se declara la variable antes de que el bloque, pero asignar el valor dentro del bloque try).

+2

Crear la secuencia también arroja 'IOException', por lo que debe estar en el' try/catch/finally' también. – Bozho

+0

Pero usar Bozho arriba haría que se guarde la excepción original, ya que básicamente está comiendo la IOException que podría lanzarse. Además, creo que probablemente debas comprobar la transmisión en busca de nulo, de lo contrario podría resultar en NPE, ¿no es así? – dcp

+1

@Bozho y dcp: en general, cuando trato con transmisiones está dentro de un método que se declara para lanzar IOException, por lo que raramente lo encuentro en ese nivel. Ahí es donde te metes en problemas. El código proporcionado aquí no necesita verificar la nulidad, ya que estoy llamando a un constructor: si ese método retorna sin excepción, 'stream' definitivamente no será nulo. –

2

En caso de que alguien es curioso la nueva sintaxis de Java 7 podría ser:

do (BufferedInputStream bis = ...; BufferedOutputStream bos = ...) { 
    ... // Perform action with bis and bos 
} 

(Ver proposal by Joshua Bloch)

Aquí es una related thread desbordamiento de pila.

Cuestiones relacionadas