todas tipos salida propagacion personalizadas mas manejo las excepciones entrada ejemplos comunes arbol java exception try-catch

salida - tipos de excepciones en java netbeans



¿La excepción de Java no está atrapada? (6)

Tengo un pequeño problema teórico con las construcciones try-catch.

Ayer hice 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 por sorpresa, no es cierto.

La respuesta correcta es ABC3 (probado y realmente es así).

Mi pregunta es, ¿a dónde fue la Excepción ("2")?


De acuerdo con tu código:

try { try { System.out.print("A"); throw new Exception("1"); // 1 } catch (Exception e) { System.out.print("B"); // 2 throw new Exception("2"); } finally { // 3 System.out.print("C"); // 4 throw new Exception("3"); } } catch (Exception e) { // 5 System.out.print(e.getMessage()); }

Como puedes ver aquí:

  1. imprima A y arroja la excepción n # 1 ;
  2. esta excepción ha sido capturada por catch statement e print B - # 2 ;
  3. block finally # 3 ejecuta después de la declaración try-catch (o solo prueba, si no se ha producido ninguna excepción) e imprime C - # 4 y lanza una nueva excepción;
  4. este ha sido capturado por la declaración de captura externa n # 5 ;

El resultado es ABC3 . Y 2 se omite de la misma manera que 1


De la Especificación del lenguaje Java 14.20.2. :

Si el bloque catch se completa bruscamente por el motivo R, entonces se ejecuta el bloque finally. Entonces hay una opción:

  • Si el bloque finally se completa normalmente, la instrucción try se completa abruptamente por el motivo R.

  • Si el bloque final se completa abruptamente por la razón S, entonces la instrucción try se completa abruptamente por la razón S (y la razón R se descarta) .

Entonces, cuando hay un bloque catch que arroja una excepción:

try { // ... } catch (Exception e) { throw new Exception("2"); }

pero también hay un bloque final que también arroja una excepción:

} finally { throw new Exception("3"); }

Exception("2") se descartará y solo se propagará la Exception("3") .


Desde throw new Exception("2"); se lanza desde el bloque catch y no lo try , no se volverá a atrapar.
Ver 14.20.2. Ejecución de try-finally y try-catch-finally .

Esto es lo que está pasando:

try { try { System.out.print("A"); //Prints A throw new Exception("1"); } catch (Exception e) { System.out.print("B"); //Caught from inner try, prints B throw new Exception("2"); } finally { System.out.print("C"); //Prints C (finally is always executed) throw new Exception("3"); } } catch (Exception e) { System.out.print(e.getMessage()); //Prints 3 since see (very detailed) link }


El bloque finally siempre se ejecuta. O return desde el bloque try o se lanza una excepción. La excepción lanzada en el bloque finally anulará la lanzada en la rama catch.

Además, lanzar una excepción no generará ningún resultado por sí mismo. La línea throw new Exception("2"); no escribirá nada.


Las excepciones arrojadas en el bloque finally suprimen la excepción lanzada anteriormente en try o catch block.

Ejemplo de Java 7: http://ideone.com/0YdeZo

Del ejemplo Javadoc''s :

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { if (br != null) br.close(); } }

Sin embargo, en este ejemplo, si los métodos readLine y close both arrojan excepciones, entonces el método readFirstLineFromFileWithFinallyBlock arroja la excepción lanzada desde el bloque finally; la excepción lanzada desde el bloque try se suprime.

La nueva sintaxis try-with de Java 7 agrega otro paso de supresión de excepciones: las excepciones lanzadas en try block suprimen aquellas lanzadas anteriormente en try-with part.

del mismo ejemplo:

try ( java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset) ) { for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) { String newLine = System.getProperty("line.separator"); String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine; writer.write(zipEntryName, 0, zipEntryName.length()); } }

Se puede lanzar una excepción del bloque de código asociado con la declaración try-with-resources. En el ejemplo anterior, se puede lanzar una excepción desde el bloque try, y se pueden lanzar hasta dos excepciones de la declaración try-with-resources cuando intenta cerrar los objetos ZipFile y BufferedWriter. Si se lanza una excepción desde el bloque try y se lanzan una o más excepciones de la declaración try-with-resources, entonces esas excepciones lanzadas desde la sentencia try-with-resources son suprimidas, y la excepción arrojada por el bloque es la excepción eso es arrojado por el método writeToFileZipFileContents. Puede recuperar estas excepciones suprimidas llamando al método Throwable.getSuppressed de la excepción lanzada por el bloque try.

En el código de la pregunta, cada bloque está descartando claramente la excepción anterior, sin siquiera iniciar sesión, lo que no es bueno cuando intenta resolver algunos errores:

http://en.wikipedia.org/wiki/Error_hiding


Su pregunta es muy obvia, y la respuesta es simple en la misma medida. El objeto Excepción con el mensaje como "2" es sobrescrito por el objeto Excepción con el mensaje como "3".

Explicación: cuando se produce una excepción, su objeto se lanza al bloque catch para manejar. Pero cuando se produce una excepción en el bloque catch, su objeto se transfiere al bloque OUTER CATCH (si existe) 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 externa. Pero espera ... Antes de salir del bloque try-catch interno TIENE QUE EJECUTAR FINALMENTE. Aquí ocurrió el cambio que nos preocupa. Se descarta un nuevo objeto EXCEPTION (con el mensaje "3") o este bloque finalmente reemplaza al objeto Exception ya lanzado (con el mensaje "2"). Como resultado, cuando se imprime el mensaje del objeto Exception, obtenemos valor invalidado, es decir, "3" y no "2".

Keep Remember: solo se puede manejar un objeto de excepción en el bloque CATCH.