2010-06-16 20 views
21

Estoy usando una grabadora con buffer y mi código, cierra el escritor en el bloque finally. Mi código es así.¿Está bien usar try catch inside finalmente?

........... 
    BufferedWriter theBufferedWriter = null; 
    try{ 
    theBufferedWriter =..... 
    .... 
    ...... 
    ..... 
    } catch (IOException anException) { 
    .... 
    } finally { 
     try { 
      theBufferedWriter.close();    
     } catch (IOException anException) { 
      anException.printStackTrace(); 
      } 
    } 

Tengo que usar el intento de captura en el código de limpieza en theBufferedWriter, finalmente, como también podría lanzar una IOException. No quiero lanzar esta excepción a la llamada methos. ¿Es una buena práctica usar una captura de prueba finalmente? Si no, ¿cuál es la alternativa? Por favor recomiende.

Saludos, Hiral

+1

está bien, pero para comprobar null primero es mejor. – qrtt1

+0

+1 No es bonito, pero tiene que hacerse –

Respuesta

14

Una forma un tanto más agradable de hacer esto es utilizar IOUtils.closeQuiety de Apache commons-io. Mantiene el código ordenado y elimina algunas de las repeticiones que son inherentes a Java.

código se convierte entonces en:

BufferedWriter theBufferedWriter = null; 
try{ 
    theBufferedWriter = ... 
    ... 
} catch (IOException anException) { 
    ... 
} finally { 
    IOUtils.closeQuietly(theBufferedWriter); 
} 

mucho más agradable y más expresiva.

+3

Cerrando un el escritor tamponado como este es arriesgado; si los caracteres permanecen en el búfer y close arroja una excepción cuando intenta escribirlos, los datos se truncan y su aplicación no maneja el error. Para que esto sea seguro, deberías llamar 'cerrar' justo antes del bloque catch. – McDowell

+2

@McDowell: es bueno saberlo. Es de suponer que también podrías llamar a 'flush()' antes del bloque catch, ¿verdad? –

+2

al cerrar el búfer lo vaciará (ver el javadoc). _En caso de que no esté claro, este patrón requiere 'close' para ser llamado dos veces. Si movieras _try/finally {close} _ al _try_ block existente, tendrías 1) solo necesitarás llamar a 'close' una vez 2) evitar la asignación 'null' redundante 3) no es necesario importar una biblioteca de terceros. Las pruebas anidadas se ven feas, pero de todos modos no se puede tomar decisiones sobre el manejo de errores de forma local, por lo que el bloque catch debería estar en una llamada más arriba de la pila de llamadas. http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html – McDowell

11

En pre Java 7, yo diría que lo que ha escrito es la mejor solución.

En Java 7 en adelante tiene Automatic Resource Management destinado a simplificar estas cosas. Con esta función, puede hacerlo

BufferedWriter theBufferedWriter = null; 
try (BufferedWriter theBufferedWriter = ...) { 
.... 
...... 
..... 
} catch (IOException anException) { 
.... 
} 
+0

Acepto intentar con recursos es el mejor enfoque desde Java 7: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – JavaDev

2

O puede utilizar Lombok y la @Cleanup anotación y que nunca escribirás un intento de captura en el interior por último de nuevo.

Esta es la forma en la que normalmente escribirlo (Nota del throws IOException):

//Vanilly Java 

import java.io.*; 

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    InputStream in = new FileInputStream(args[0]); 
    try { 
     OutputStream out = new FileOutputStream(args[1]); 
     try { 
     byte[] b = new byte[10000]; 
     while (true) { 
      int r = in.read(b); 
      if (r == -1) break; 
      out.write(b, 0, r); 
     } 
     } finally { 
     out.close(); 
     } 
    } finally { 
     in.close(); 
    } 
    } 
} 

Ahora con Lombok que acaba de escribir @Cleanup en las corrientes

import lombok.Cleanup; 
import java.io.*; 

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    @Cleanup InputStream in = new FileInputStream(args[0]); 
    @Cleanup OutputStream out = new FileOutputStream(args[1]); 
    byte[] b = new byte[10000]; 
    while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
    } 
    } 
} 
1

Está bien, pero debe probar si theBufferedWriter no es nulo antes de cerrarlo.
También puede hacer:

BufferedWriter theBufferedWriter; 
try { 
    theBufferedWriter = new ... 
    try { 
     ... 
    } finally { 
     try { 
      theBufferedWriter.close(); 
     } catch (IOException closeException) { 
      closeException.printStackTrace(); 
     } 
    } 
} catch (IOException anException) { 
    ... 
} 

o:

BufferedWriter theBufferedWriter; 
try { 
    theBufferedWriter = new ... 
} catch (IOException createException) { 
    // do something with createException 
    return; // assuming we are in a method returning void 
} 

try { 
    ... 
} catch (IOException anException) { 
    ... 
    // assuming we don't return here 
} 

try { 
    theBufferedWriter.close(); 
} catch (IOException closeException) { 
    closeException.printStackTrace(); 
} 

pero sobre todo hacer este tipo de operaciones (por ejemplo, escribir un archivo) en un método específico y prefieren tirar la/una excepción por lo que la persona que llama puede manejar la situación (por ejemplo, pidiendo otro archivo, detener la aplicación, ...):

void someMethod(...) throws IOException { 
    BufferedWriter theBufferedWriter = new ... 

    try { 
     ... 
    } catch (IOExcepption anException) { 
     try { 
      theBufferedWriter.close(); 
     } catch (IOException closeException) { 
      closeException.printStackTrace(); 
      // closeException is not thrown, anException represents the main/first problem 
     } 
     throw anException; 
    } 

    theBufferedWriter.close(); // throws the Exception, if any 
} 

Tenga en cuenta: Inglés no es mi abetos t ni mi segundo idioma, cualquier ayuda sería apreciada

0

Está bien poner un try-catch en un final. Es la herramienta que hace lo que quieres hacer. Sin embargo, creo que la IOException lanzada de cerca es bastante poco común como para permitir que suprima cualquier excepción en el cuerpo.

try { 
    BufferedWriter writer = ..... 
    try { 
     ..... 
    } finally { 
     writer.close(); 
    } 
} catch (IOException e) { 
    .... 
}