De regresar de un bloque finally en Java

Me sorprendió recientemente a encontrar que es posible tener una instrucción return en un bloque finally en Java.

Parece como un montón de gente piensa que es una mala cosa que hacer, como se describe en ‘No volver en una cláusula finally‘. Rascando un poco más, también me encontré a ‘Java retorno no siempre‘, que muestra algunos bastante horribles ejemplos de otros tipos de control de flujo en bloques finally.

Así, mi pregunta es, ¿alguien puede darme un ejemplo de una instrucción return (o de otras control de flujo) en un bloque finally se produce mejor /código más legible?

OriginalEl autor Matt Sheppard | 2008-09-07

5 Kommentare

  1. 79

    Los ejemplos que siempre son motivo más que suficiente para no el uso de control de flujo de finalmente.

    Incluso si hay un ejemplo inventado donde es «mejor» considerar la posibilidad de que el desarrollador que tiene que mantener el código lo más tarde y que podría no ser consciente de las sutilezas. Que buenos desarrollador incluso podría ser que….

    Seguro. Supongo que estoy pidiendo en caso de que alguien me puede dar algunas realmente convincente ejemplo en el lado del bien.
    en daos, voy a menudo registro de la salida de una consulta en un try-finally

    OriginalEl autor Jason Cohen

  2. 127

    Tuve un momento MUY difícil para rastrear a un bug de hace años, que fue causado por este. El código sería algo como:

    Object problemMethod() {
        Object rtn = null;
        try {
            rtn = somethingThatThrewAnException();
        }
        finally {
            doSomeCleanup();
            return rtn;
        }
    }

    Lo que sucedió es que la excepción fue lanzado en algún otro código. Estaba siendo capturado y registra y se vuelve a producir dentro de la somethingThatThrewAnException() método. Pero la excepción no se propaga hasta pasado problemMethod(). Después de un LARGO tiempo de mirar este que finalmente relacionarlo con el método de declaración. El método de declaración en el bloque finally se trataba básicamente de detener la excepción que ocurrió en el bloque try se propaguen a pesar de que no estaba atrapado.

    Como otros han dicho, aunque es legal regreso de un bloque finally, de acuerdo a la especificación de Java, es una cosa MALA y no se debe hacer.

    OriginalEl autor John Meagher

  3. 19

    javac advertirá de regreso en por último, si se utiliza el-Xlint:finalmente. Originalmente javac emitido ninguna advertencia – si algo está mal con el código, se producirá un error de compilación. Por desgracia compatibilidad hacia atrás, significa que no previstos ingenioso locura no puede ser prohibido.

    Excepciones que pueden ser lanzadas desde bloques finally, pero en caso de que la exhibieron comportamiento es casi seguro que lo que usted desea.

    OriginalEl autor Tom Hawtin – tackline

  4. 13

    La adición de estructuras de control y vuelve a finalmente{} los bloques son más que otro ejemplo de «sólo porque se puede» de los abusos que se dispersan a lo largo de prácticamente todos los lenguajes de desarrollo. Jason estaba en lo correcto en lo que sugiere que podría fácilmente convertirse en una pesadilla de mantenimiento – los argumentos en contra de los rendimientos de las funciones de aplicar más aún, para este caso de «los rendimientos finales».

    Finalmente bloques existen para un propósito, para permitir a totalmente ordenado hasta después de ti, no importa lo que pasó en el anterior código. Principalmente este es el cierre de /la liberación de punteros a archivos, conexiones de base de datos, etc., a pesar de que yo podría ver que se extendía a decir añadiendo en la medida de auditoría.

    Nada de lo que afecta a la devolución de la función debe estar en el try{} bloque. Incluso si usted tenía un método por el cual se comprueba una externa del estado, hizo un tiempo de consumo de la operación, entonces se comprueba que el estado de nuevo en caso de que ya no era válida, usted todavía desea que la segunda verificación dentro del try{} – si él se sentó en el interior finalmente{} y el tiempo de operación de error, entonces usted podría ser la comprobación de que el estado de un segundo tiempo innecesariamente.

    OriginalEl autor Ian

  5. 5

    Un simple Groovy Prueba:

    public class Instance {
    
      List<String> runningThreads = new ArrayList<String>()
    
      void test(boolean returnInFinally) {
    
        println "\ntest(returnInFinally: $returnInFinally)"
        println "--------------------------------------------------------------------------"
        println "before execute"
        String result = execute(returnInFinally, false)
        println "after execute -> result: " + result
        println "--------------------------------------------------------------------------"
    
        println "before execute"
        try {
          result = execute(returnInFinally, true)
          println "after execute -> result: " + result
        } catch (Exception ex) {
          println "execute threw exception: " + ex.getMessage()
        }  
        println "--------------------------------------------------------------------------\n"
    
      }
    
      String execute(boolean returnInFinally, boolean throwError) {
          String thread = Thread.currentThread().getName()
          println "...execute(returnInFinally: $returnInFinally, throwError: $throwError) - thread: $thread"
          runningThreads.add(thread)
          try {
            if (throwError) {
              println "...error in execute, throw exception"
              throw new Exception("as you liked :-)")
            }
            println "...return 'OK' from execute"
            return "OK"
          } finally {
            println "...pass finally block"
            if (returnInFinally) return "return value from FINALLY ^^"
            //runningThreads.remove(thread)
          }
      }
    }
    
    Instance instance = new Instance()
    instance.test(false)
    instance.test(true)

    De salida:

    test(returnInFinally: false)
    -----------------------------------------------------------------------------
    before execute
    ...execute(returnInFinally: false, throwError: false) - thread: Thread-116
    ...return 'OK' from execute
    ...pass finally block
    after execute -> result: OK
    -----------------------------------------------------------------------------
    before execute
    ...execute(returnInFinally: false, throwError: true) - thread: Thread-116
    ...error in execute, throw exception
    ...pass finally block
    execute threw exception: as you liked :-)
    -----------------------------------------------------------------------------
    
    
    test(returnInFinally: true)
    -----------------------------------------------------------------------------
    before execute
    ...execute(returnInFinally: true, throwError: false) - thread: Thread-116
    ...return 'OK' from execute
    ...pass finally block
    after execute -> result: return value from FINALLY ^^
    -----------------------------------------------------------------------------
    before execute
    ...execute(returnInFinally: true, throwError: true) - thread: Thread-116
    ...error in execute, throw exception
    ...pass finally block
    after execute -> result: return value from FINALLY ^^
    -----------------------------------------------------------------------------

    Pregunta:

    Un punto interesante para mí fue ver cómo Groovy ocupa implícito devuelve. En Groovy es posible «volver» a partir de un método simplemente dejando un valor al final (sin retorno). ¿Qué crees que sucede, si usted quite el comentario de la runningThreads.quitar(..) línea en la que finalmente declaración – esta sobrescribir el regular el valor de retorno («ACEPTAR») y cubrir la excepción?!

    OriginalEl autor Prof. Ondino

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea