2011-10-04 22 views
5

mayoría de las veces, la única cosa que veo un bloque finalmente utilizado para algo así como¿Por qué tengo que usar finalmente para cerrar recursos?

FileInputStream f; 
try{ 
    f= new FileInputStream("sample.txt"); 
    //something that uses f and sometimes throws an exception 
} 
catch(IOException ex){ 
    /* Handle it somehow */ 
} 
finally{ 
    f.close(); 
} 

Mi pregunta es, si F alcance termina con el bloque que lo contiene, ¿por qué necesitamos para cerrarla en el fin ?

+0

En su caso, el alcance de 'f' no termina con el try-block –

+0

@Oli Charlesworth: Este es claramente un ejemplo legible. –

+0

La creación de una referencia de archivo no arroja excepciones (o crea un manejador de archivo), para referencia futura. –

Respuesta

18

Porque la recolección de basura es no lo mismo que la limpieza de recursos.

Por ejemplo, si tiene un objeto de conexión JDBC que está fuera del alcance, no hay señal enviada al servidor de la base de datos para indicar que los cursores abiertos y las conexiones ya no son necesarios. Sin esos mensajes, eventualmente agotarás la cantidad de cursores y conexiones disponibles para ti.

Lo mismo con identificadores de archivos y cualquier otro recurso. Limpia después de ti mismo.

+2

Sí, por supuesto. Pero ¿por qué 'finalmente'? –

+5

Porque se garantiza que se ejecutará el código en el bloque finally, incluso si se lanza una excepción. – duffymo

+1

@Joe buen ejemplo. Pero nunca devuelva algo en un bloque final si tiene un bloque catch que arroje una excepción. en ese caso, su excepción nunca será lanzada ... la aprendo de la manera más difícil ;-) – Cygnusx1

6

Bueno, ha dado un mal ejemplo - sospecho que se refería a algo como FileInputStream - pero la razón básica es que Java no tiene una finalización determinista.

El alcance de la variablesf termina con el bloque que está declarada en (no el bloque try), pero eso no quiere decir que hay necesariamente ninguna referencia "en vivo" en el objeto más - y el recolector de basura no finalizará el objeto ni la basura lo recogerá de manera determinista.

A menos que desee dejar los recursos dando vueltas por un período de tiempo arbitrario (y demorar la recolección de elementos no utilizados, ya que los finalizadores requieren una ronda adicional de recolección antes de liberar finalmente la memoria), debe cerrar los recursos de forma explícita.

Básicamente Java hace no admite RAII de la misma manera que C++; no deberías tratar de usarlo como si fuera C++.

+0

Editada para reflejar su sugerencia: me acaba de ocurrir un Closeable de memoria, así que gracias por darme uno que realmente se aplica :PAG –

0

La razón es que Java no garantiza que un objeto se recolecte basura tan pronto como una referencia particular caiga fuera del alcance. Por lo tanto, para objetos que hacen referencia a recursos limitados del sistema, como un descriptor de archivo, no es suficiente esperar a que se recoja basura.

Sin embargo, tenga en cuenta que java.io.File no es realmente un objeto así.

1

porque finalmente se llama cada vez, incluso si se produce una excepción. el bloque finally le asegura que el archivo/conexión se cerrará.

0

Manejamos la excepción por try catch finalmente, finalmente bloqueamos cada vez que ejecutamos pero no hay garantía de catch porque catch block se ejecuta solo si se pasa una excepción en el parámetro coincidente. Por ejemplo, si tenemos abierta alguna conexión de base de datos, entonces debemos cerrarla antes de irnos, debe implementarse finalmente.

Cuestiones relacionadas