¿Por qué usamos finalmente bloques?

91

Por lo que puedo decir, los dos fragmentos de código siguientes servirán para el mismo propósito. ¿Por qué tener finallybloques?

Codigo A:

try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }

Código B:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code
Mohammad Nadeem
fuente
Esto no es específico de C #, es una pregunta de .Net
2010
1
Ya no es necesario con java7: AutomaticResourceManagement, pruebe (new resourceDeclartion ()) {}
Kanagavelu Sugumar

Respuestas:

139
  • ¿Qué sucede si se lanza una excepción que no está manejando? (Espero que no te estés contagiando Throwable...)
  • ¿Qué sucede si regresa desde el interior del bloque try?
  • ¿Qué sucede si el bloque catch lanza una excepción?

Un finallybloque se asegura de que, sin embargo , salga de ese bloque (módulo algunas formas de abortar todo el proceso explícitamente), se ejecutará. Eso es importante para la limpieza determinista de recursos.

Jon Skeet
fuente
48
No es necesariamente cierto; finalmente no se ejecutará si (1) hay una System.exit()llamada (2) hay un bucle infinito en el intento o en uno del bloque de captura (3) desconecto la computadora
NullUserException
2
@Alon try {return 1; } finalmente {retrun 2; } Obtendrá 2
Dennis C
19
@NullUserException: de ahí el bit "módulo de algunas formas ..."
Jon Skeet
2
John Skeet vive aquí en stackoverflow, cada pregunta es como un timbre que tiene que responder :)
naikus
1
Esta publicación analiza las (raras) condiciones bajo las cuales finalmente NO SERÁ llamado.
Candamir
13

Tenga en cuenta que (al menos en Java, probablemente también en C #) también es posible tener un trybloque sin un catch, pero con un finally. Cuando ocurre una excepción en el trybloque, el código en el finallybloque se ejecuta antes de que la excepción se lance más arriba:

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}
Jesper
fuente
7

Es posible que desee poner el código que desea que se ejecute de todos modos, independientemente de lo que suceda en su bloque try o catch.

Además, si está utilizando capturas múltiples y si desea colocar algún código que sea común para todos los bloques de captura, este sería un lugar para colocar, pero no puede estar seguro de que se haya ejecutado todo el código en try.

Por ejemplo:

conn c1 = new connection();
try {
    c1.dosomething();
} catch (ExceptionA exa) {
    handleexA();
    //c1.close();
} catch (ExceptionB exb) {
    handleexB();
    //c1.close();
} finally {
    c1.close();
}
Balaji Natesan
fuente
1
¿Qué pasa si no utilizo 'finalmente' pero cierro la conexión?
Istiaque Ahmed
5

Finalmente siempre se ejecuta, mientras que su código después de la captura puede que no.

Sruly
fuente
1
¡Por qué no! Si la excepción se maneja correctamente, el código se ejecutará definitivamente.
Mohammad Nadeem
1
@Nadeem: Vea mi respuesta por 3 razones por las que puede que no suceda.
Jon Skeet
2

Aunque nuestra aplicación se cierre forzosamente, habrá algunas tareas, que debemos ejecutar (como liberación de memoria, cierre de base de datos, liberación de bloqueo, etc.), si escribe estas líneas de código en el finallybloque, se ejecutará si se lanza una excepción o no...

Su aplicación puede ser una colección de hilos, Exceptiontermina el hilo pero no toda la aplicación, en este caso finallyes más útil.

En algunos casos finallyno se ejecutará, como JVM Fail, Thread terminate, etc.

Sandeep P
fuente
1

Porque necesita que ese código se ejecute independientemente de las excepciones que puedan producirse. Por ejemplo, es posible que deba limpiar algún recurso no administrado (la construcción 'using' se compila en un bloque try / finalmente).

Ed S.
fuente
0

Puede haber ocasiones en las que desee ejecutar un fragmento de código sin importar qué. Si se lanza una excepción o no. Entonces uno usa finally.

Igualitario
fuente
0

finally SIEMPRE se ejecuta, a menos que se apague la JVM, finally solo proporciona un método para colocar el código de limpieza en un solo lugar.

Sería demasiado tedioso si tuviera que poner el código de limpieza en cada uno de los catchbloques.

Mahmoud Hanafy
fuente
0

Si el bloque catch arroja alguna excepción, el código restante no se ejecutará, por lo tanto, tenemos que escribir el bloque final.

Reshma Kore
fuente
0

Finalmente, el bloque en Java se puede usar para poner código de "limpieza", como cerrar un archivo, cerrar una conexión, etc.


El bloque finalmente no se ejecutará si el programa sale (ya sea llamando a System.exit () o provocando un error fatal que hace que el proceso se anule).

Aakersh Sharma
fuente
0

¿Sigues desplazándote hacia abajo? ¡Aqui tienes!

Esta pregunta me hizo retroceder un tiempo.

try
{
 int a=1;
 int b=0;
 int c=a/b;
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}
finally
{
 console.writeline("Finally block");
}
console.writeline("After finally");

¿Qué se imprimiría en el escenario anterior? Sí, lo acerté:

  • ej., mensaje - lo que sea (probablemente intento de división por cero)

  • Finalmente bloquear

  • Después de finalmente

    try
    {
        int a=1;
        int b=0;
        int c=a/b;
    }
    catch(Exception ex)
    {
        throw(ex);
    }
    finally
    {
        console.writeline("Finally block");
    }
    console.writeline("After finally");
    

¿Qué imprimiría esta? ¡Nada! Lanza un error ya que el bloque catch generó un error.

En una buena estructura de programación, sus excepciones se canalizarían, en el sentido de que este código se manejará desde otra capa. Para estimular tal caso, probaré este código.

try
{    
 try
    {
     int a=1;
     int b=0;
     int c=a/b;
    }
    catch(Exception ex)
    {
     throw(ex);
    }
    finally
    {
     console.writeline("Finally block")
    }
    console.writeline("After finally");
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}

En este caso, la salida sería:

  • Finalmente bloquear
  • por ejemplo, mensaje, sea lo que sea.

Está claro que cuando detecta una excepción y la lanza nuevamente a otras capas (Funneling), el código después del lanzamiento no se ejecuta. Actúa de manera similar a cómo funciona un retorno dentro de una función.

Ahora sabe por qué no cerrar sus recursos en códigos después del bloque de captura. Colóquelos en el bloque finalmente.

Ashique razak
fuente