2011-01-17 30 views
8
static int retIntExc() throws Exception{ 
    int result = 1; 
    try { 
     result = 2; 
     throw new IOException("Exception rised."); 
    } catch (ArrayIndexOutOfBoundsException e) { 
     System.out.println(e.getMessage()); 
     result = 3; 
    } finally { 
     return result; 
    } 
} 

Un amigo mío es un desarrollador .NET y actualmente está migrando a Java y me hace la siguiente pregunta sobre esta fuente. En teoría, esto debe ser throw IOException("Exception rised.") y todo el método retIntExc() debe throws Exception. Pero no ocurre nada, el método devuelve 2.Se omite la excepción finalmente

No he probado su ejemplo, pero creo que este no es el comportamiento esperado.

EDIT: Gracias por todas las respuestas. Algunos de ustedes han ignorado el hecho de que el método se llama retIntExc, lo que significa que este es solo un ejemplo de prueba/experimental, que muestra un problema en la mecánica de lanzar/atrapar. No necesitaba 'arreglar', necesitaba una explicación de por qué sucede esto.

+0

¿Por qué no lo declara 'throws IOException'? – BoltClock

+0

http://stackoverflow.com/questions/65035/in-java-does-return-trump-finally –

Respuesta

16

Es por esto que no se puede volver a partir de un bloque finally en C# :)

Es absolutamente el comportamiento presentado en el Sin embargo, la especificación del lenguaje Java. Está especificado en section 14.20.2.

Si el bloque finally se completa abruptamente por el motivo S, entonces la instrucción try se completa bruscamente por el motivo S (y el lanzamiento del valor V se descarta y se olvida).

Devolución es un ejemplo de completar abruptamente; si el bloque finally arrojó una excepción, eso sería también completa abruptamente, perdiendo la excepción original.

La cita anterior era de este conjunto anidado de viñetas, dejando de lado las opciones que no son aplicables aquí:

  • Si la ejecución del bloque try termina abruptamente debido a un lanzamiento de un valor V, entonces hay una opción:
    • Si el tipo de V en tiempo de ejecución no es asignable al parámetro de ninguna cláusula catch de la instrucción try, entonces se ejecuta el bloque finally. Luego hay una opción:
      • Si el bloque finally se completa bruscamente por el motivo S, entonces la instrucción try se completa bruscamente por el motivo S (y el lanzamiento del valor V se descarta y se olvida).
+2

Gracias. Esto es lo que necesitaba: referencia JLS. – fiction

3

Se volverá 2 porque

finally siempre ejecutar

+0

-1 ** finalmente no siempre se ejecuta ** y no imprime nada. – Ishtar

+0

por favor intente esto. System.out.println (retIntExc()); ¡y piense twise antes de votar cualquier cosa! –

+0

finalmente no siempre se ejecuta. – Woot4Moo

2

El bloque finally ejecuta sin importar lo que excepción. No solo se ejecuta después de que las excepciones son capturadas por los bloques catch que usted declara. Se ejecuta después del try bloque y excepciones capturadas si alguna. Si su método arroja una excepción, no puede devolver nada a menos que usted lo trague dentro de su método y devuelva result. Pero no puedes tener ambos.

Además, a menos que su método tenga otro código, nunca se encontrará con ArrayIndexOutOfBoundsException.

0

El clase IOException no es un niño de la clase ArrayIndexOutOfBoundsException lo que la parte de captura no será ejecutado.

Si cambia a esta se volverá 3.

static int retIntExc() throws Exception{ 
     int result = 1; 
     try { 
      result = 2; 
      throw new ArrayIndexOutOfBoundsException ("Exception rised."); 
     } catch (ArrayIndexOutOfBoundsException e) { 
      System.out.println(e.getMessage()); 
      result = 3; 
     } finally { 
      return result; 
     } 
    } 
2

Esto es porque se emite una instrucción de retorno antes de que la excepción se pasa a través y por lo tanto se devuelve un valor válido. No se puede devolver un valor y lanzar una excepción.

Al eliminar el bloque finally alrededor de la devolución obtendrá el comportamiento que desea.

0

No veo por qué no se esperaría este comportamiento. A finales de este resultado bloque de código es igual a 2.

static int retIntExc() throws Exception{ 
     int result = 1; 
     try { 
      result = 2; 

A continuación, lanza una excepción, pero su bloque catch detecta excepciones de un tipo diferente de modo que nada se ejecuta.

 throw new IOException("Exception rised."); 
    } catch (ArrayIndexOutOfBoundsException e) { 
      ... 
    } 

El bloque finally está garantizada para ser ejecutado, por lo que el paso final es volver 2.

Este exitoso retorno anula la excepción de propagación. Si desea que la excepción continúe burbujeando, no debe regresar en el bloque finally.

0

Al poner return en el método finally se anula la excepción lanzada y se devuelve el resultado. Su código debería ser algo como esto:

static int retIntExc() throws Exception{ 
     int result = 1; 
     try { 
      result = 2; 
      throw new IOException("Exception rised."); 
     } catch (ArrayIndexOutOfBoundsException e) { 
      System.out.println(e.getMessage()); 
      result = 3; 
     } finally { 
      // do something 
     } 
     // it gets here only when exception is not thrown 
     return result; 
    } 
Cuestiones relacionadas