Tengo un pequeño problema teórico con las construcciones try-catch.
Ayer tomé un examen práctico sobre Java y no entiendo el siguiente ejemplo:
try {
try {
System.out.print("A");
throw new Exception("1");
} catch (Exception e) {
System.out.print("B");
throw new Exception("2");
} finally {
System.out.print("C");
throw new Exception("3");
}
} catch (Exception e) {
System.out.print(e.getMessage());
}
La pregunta era "¿cómo se verá la salida?"
Estaba bastante seguro de que sería AB2C3, PERO sorpresa sorpresa, no es cierto.
La respuesta correcta es ABC3 (probado y realmente es así).
Mi pregunta es, ¿a dónde se fue la Excepción ("2")?
print(e.getMessage())
. Pensaste que la salida seríaAB2C3
: ¿creías que elcatch
bloque más externo se ejecutaría dos veces?Respuestas:
De la especificación del lenguaje Java 14.20.2. :
Entonces, cuando hay un bloque catch que arroja una excepción:
pero también hay un bloque finalmente que también arroja una excepción:
Exception("2")
será descartado y soloException("3")
se propagará.fuente
return
declaraciones. Si su bloque finalmente tiene un retorno, anulará cualquier retorno en un bloquetry
ocatch
. Debido a estas "características", una buena práctica es que finalmente block nunca debe lanzar una excepción o tener una declaración return.Las excepciones lanzadas finalmente en el bloque suprimen la excepción lanzada anteriormente en el bloque try o catch.
Ejemplo de Java 7: http://ideone.com/0YdeZo
Del ejemplo de Javadoc :
La nueva
try-with
sintaxis de Java 7 agrega otro paso de supresión de excepciones: las excepciones lanzadas en el bloque try suprimen las lanzadas anteriormente en la parte try-with.del mismo ejemplo:
En el código de la pregunta, cada bloque descarta la antigua excepción, ni siquiera lo registra, lo que no es bueno cuando intenta resolver algunos errores:
http://en.wikipedia.org/wiki/Error_hiding
fuente
Como
throw new Exception("2");
se arroja desde elcatch
bloque y notry
, no se volverá a atrapar.Ver 14.20.2. Ejecución de try-finally y try-catch-finally .
Esto es lo que está sucediendo:
fuente
Su pregunta es muy obvia, y la respuesta es simple en la misma medida. El objeto de excepción con mensaje como "2" se sobrescribe con el objeto de excepción con mensaje como "3".
Explicación: Cuando ocurre una Excepción, su objeto se lanza para atrapar bloque para manejar. Pero cuando ocurre una excepción en el bloque catch, su objeto se transfiere al bloque OUTER CATCH (si corresponde) para el manejo de excepciones. Y lo mismo sucedió aquí. El objeto de excepción con el mensaje "2" se transfiere al bloque de captura OUTER. Pero espere ... Antes de salir del bloque try-catch interno, TIENE QUE EJECUTAR FINALMENTE. Aquí ocurrió el cambio que nos preocupa. Se arroja un nuevo objeto EXCEPTION (con el mensaje "3") o finalmente este bloque que reemplazó al objeto Exception ya lanzado (con el mensaje "2"). Como resultado de esto, cuando se imprime el mensaje del objeto Exception, tenemos valor anulado, es decir, "3" y no "2".
Keep Remember: solo se puede manejar un objeto de excepción en el bloque CATCH.
fuente
El
finally
bloque siempre corre. Oreturn
desde dentro del bloque try o se lanza una excepción. La excepción lanzada en elfinally
bloque anulará la lanzada en la rama catch.Además, lanzar una excepción no causará ningún resultado por sí solo. La línea
throw new Exception("2");
no escribirá nada.fuente
De acuerdo a su código:
Como puedes ver aquí:
# 1
;B - # 2
;# 3
ejecuta después de la declaración try-catch (o solo try, si no se ha producido ninguna excepción) e imprimeC - # 4
y lanza una nueva excepción;# 5
;El resultado es
ABC3
. Y2
se omite de la misma manera que1
fuente