2010-06-30 16 views
8

Creo que en los siguientes ejemplos; pero no pude entender cuál es la importancia del bloque final. ¿Puede decirme la diferencia de las ejecuciones de estos dos ejemplos de código? También un ejemplo de la vida real puede ser útil.¿Cuál es la esencia del bloque finally en Java?

Muestra 1:

try{ 
     // some code 1 
    }catch(Exception ex){ 
     // print exception 
    }finally{ 
     // some code 2    
    } 

Muestra 2:

try{ 
     // some code 1 
    }catch(Exception ex){ 
     // print exception 
    } 
    // some code 2 
+0

Tenga en cuenta que rara vez es útil disponer de un 'try' comunicado tanto con un' catch' y una 'finalmente' si no quieres código desordenado. –

+0

@Tom ¿por qué es eso? sirven para dos propósitos completamente diferentes, la captura es para el manejo de fallas, finalmente es para el manejo de recursos. – james

+0

@james Sí, tienen usos completamente diferentes, lo que significa que su alcance también debería ser diferente. –

Respuesta

17

Hay una gran diferencia en los dos fragmentos que ha presentado, p. Ej. cuando el bloque catch arroja una excepción, el bloque finally todavía se ejecutará por su semántica.

Ese es el siguiente fragmento de código imprime "Finally!", pero no "What about me???":

try { 
     throw null;  // throws NullPointerException! 
    } catch (Exception e) { 
     int oops = 1/0; // throws ArithmeticException! 
    } finally { 
     System.out.println("Finally!"); // still gets executed! 
    } 
    System.out.println("What about me???"); // doesn't get executed! 

En términos generales, la finally de un bloque try prácticamente siempre es ejecutado. No hay tal garantía para ningún código que siga el bloque try.


Pero ¿y si mi bloque catch es sólo un simple print declaración?

Todavía hay ninguna garantía de que no lo hará throw algo. Algo podría salir mal, por ejemplo la construcción del mensaje detallado de excepción.

Incluso si hace un mejor esfuerzo, garantiza que el código catch es "seguro" y siempre se ejecutará el código que sigue a la declaración try, entonces la pregunta es "¿Por qué?". ¿Por qué evitar finally pero luego intentas tanto para replicar su semántica?

finally semántica está garantizada, no requiere ninguna carga de la prueba del escritor o el lector del código. Precisamente debido a esto, es idiomático para usar el bloque finally para poner el código obligatorio de "limpieza". El uso de finally garantiza la corrección y mejora la capacidad de escritura y la legibilidad.

+0

Entendí la idea. En el caso en que acabo de llamar a la función de impresión en bloque catch, ¿finalmente no tiene importancia? – abuzittin

+0

@abuzittin: más que la semántica, el PATRÓN en sí mismo es importante. Es idiomático poner códigos de limpieza obligatorios en "finalmente". La semántica 'finalmente' hace que la intención sea mucho más clara. Además, una impresión simple puede, en algunas circunstancias, arrojar una excepción (por ejemplo, 'IOException', el registrador se volvió loco, la construcción del mensaje salió mal, etc.). – polygenelubricants

+1

Tenga en cuenta que aún no se puede ejecutar si ocurre algo catastrófico (por ejemplo, el usuario cancela el proceso o desconecta la máquina), pero en lo que respecta a las excepciones, está bien. –

2

Se utiliza el bloque de finally con el fin de limpieza y ejecutar cualquier código que se debe ejecutar si se produce una excepción (y atrapó) o no. Esto incluye el código que tiene en el bloque catch.

+0

¿Quiere decir, si tengo un código de bloque catch que puede arrojar una excepción? En el caso en que acabo de llamar a la función de impresión, finalmente no tiene importancia ?? – abuzittin

8

El bloque finally se ejecuta incluso si, p. Se arroja un Error, que no es capturado por el bloque catch en su ejemplo. De modo que puede poner código de limpieza en el bloque finally, que debe ejecutarse siempre, independientemente del resultado de las operaciones en los bloques try y catch.

Tenga en cuenta que generalmente los bloques catch detectan tipos más específicos de excepciones, a menudo solo se marcan excepciones, por lo que en la mayoría de los casos la diferencia entre los dos ejemplos de código anteriores es muy clara.

Actualización: puede decir que su bloque catch nunca puede lanzar una excepción, por lo finally no es necesario. Sin embargo, tenga en cuenta dos cosas:

  • esto es sólo el actual estado del código, y puede cambiar en el futuro - se puede garantizar que el futuro programador que añade un poco de código potencialmente excepción de lanzamiento en el catch bloquear, ¿recuerdas poner el código de limpieza después en un bloque finally?
  • try-catch-finally es un idioma de programación que hace que sea más fácil para las personas que leen el código entender lo que está sucediendo. Si no usas el idioma común, te arriesgas a malentendidos, y por lo tanto a errores a largo plazo.
+0

Excepción o error. Si volvemos a pensar mi pregunta con Error en lugar de Excepción, ¿cuál será su respuesta? – abuzittin

+0

Gracias por su parte de actualización. – abuzittin

+0

@abuzittin, mientras tanto, he actualizado mi publicación, lo que creo que responde a su pregunta. Por cierto, debería ser 'Throwable', no' Error'. –

1

es útil cuando queremos liberar los recursos que usamos en try block. Entonces, el único lugar para ejecutarlos sin fallar en ningún caso es finalmente bloquear. Dado que si se lanza una excepción, Java no ejecuta el código inmediatamente después de eso. salta directamente al bloque catch.

0

Tenga en cuenta que usted puede tener incluso intentar-finalmente sin un inconveniente:

try{ 
    // some code 
}finally{ 
    // cleanup code 
} 

Un ejemplo lo tanto, podría ser un método que quiere propagar excepciones a la persona que llama, pero todavía necesita código de limpieza, como la liberación de una Mira.

0

En caso de que las instrucciones en el bloque try arrojen excepciones no verificadas, finalmente se ejecutará el bloque permitiendo al programador tomar las medidas pertinentes.

0

En la vida real, el bloque finally se usa para cerrar recursos abiertos incluso si se produce una excepción. Por ejemplo, cuando se lee (o escribir) un archivo, cuando se accede a una base de datos, etc.

public void readFile(String fileName) { 
    FileReader fr; 
    BufferedFileReader bfr; 

    try { 
     fr = new FileReader(fileName); 
     bfr = new BufferedFileReader(fr); 
     // ... 
    } catch (IOException ioe) { 
     // ... 
    } finally { 
     // TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES 
     if (bfr != null) { 
      try { 
       bfr.close(); 
      } catch (IOException ignoredIOE) {} 
     } 
     if (fr != null) { 
      try { 
       fr.close(); 
      } catch (IOException ignoredIOE) {} 
     } 
    } 
} 
Cuestiones relacionadas