java - net - ¿Por qué try..finally block no registra la excepción original como suprimida?
try catch c# asp net (2)
Debido a que try-with-resources es azúcar sintáctica y el compilador de Java no expande los bloques regulares try-finally de la misma manera.
Eche un vistazo al siguiente código:
try(FileInputStream fstream = new FileInputStream("test")) {
fstream.read();
}
Cuando se compila y luego se descompila (usando IntelliJ IDEA) se ve así:
FileInputStream fstream = new FileInputStream("test");
Throwable var2 = null;
try {
fstream.read();
} catch (Throwable var19) {
var2 = var19;
throw var19;
} finally {
if(fstream != null) {
if(var2 != null) {
try {
fstream.close();
} catch (Throwable var17) {
var2.addSuppressed(var17);
}
} else {
fstream.close();
}
}
}
Considerando este código:
FileInputStream fstream = new FileInputStream("test");
try {
fstream.read();
} finally {
fstream.close();
}
Se ve exactamente igual cuando se compila y se descompila.
Ahora, definitivamente se podría hacer el caso de que todos los bloques finally
se deberían expandir de la misma manera que se hizo anteriormente, pero por alguna razón eso se ha pasado por alto o se ha decidido en contra.
Le sugiero que abra una solicitud de función para esto porque creo que es una función sensata.
Con el siguiente código:
try {
throw new RuntimeException ("main");
}
finally {
throw new RuntimeException ("finally");
}
Obtengo este resultado:
Exception in thread "main" java.lang.RuntimeException: finally
at test.main(test.java:12)
Sin embargo, con la adición de excepciones suprimidas en Java 7, ¿no sería lógico que el lenguaje registrara la excepción "principal" original como suprimida cuando finally
bloque falla con excepción? Actualmente tengo que emular esto manualmente:
try {
throw new RuntimeException ("main");
}
catch (RuntimeException exception) {
try {
throw new RuntimeException ("finally");
}
catch (RuntimeException exception2) {
exception2.addSuppressed (exception);
throw exception2;
}
}
para recibir un resultado más útil (para comprender lo que está sucediendo):
Exception in thread "main" java.lang.RuntimeException: finally
at test.main(test.java:13)
Suppressed: java.lang.RuntimeException: main
at test.main(test.java:9)
EDITAR: Para aclarar lo que estoy pensando. La versión actual de Java es 8, las excepciones suprimidas no son una característica nueva. Pero try..finally
todavía no los incorpora. ¿Hay algo que evite que esto suceda?
Esta no es una respuesta autorizada, pero parece que tal cambio podría romper la compatibilidad o try-with-resources
e try-finally
ser inconsistente entre sí.
La semántica en try-with-resources
es que la excepción lanzada desde el bloque try
se propaga, con la excepción lanzada al invocar el método close()
registrado como suprimido. Esto tiene sentido desde un punto de vista práctico, desea capturar su excepción "real" y, a continuación, tal vez también lidiar con el recurso que no se cierra si lo desea.
Pero al try-finally
es la excepción lanzada al finally
que se propaga (mientras que la del try
se "traga") y, por lo tanto, tenemos la opción de tres soluciones malas:
- Invierta la lógica de
try-finally
para alinearlo con la compatibilidad detry-with-resources
y el código de ruina (o mejor dicho, bug) con todo el código anterior. - Siga propagando la excepción "
close()
" con la excepcióntry
registrada como suprimida, haciendo que las dos construcciones sean inconsistentes entre sí. - Solo deja todo como está.
Subjetivamente, veo 3 como menos malo que 1 o 2, aunque es bastante fácil argumentar lo contrario. Sin embargo, sospecho que este fue un dilema al que se enfrentaron los desarrolladores de lenguajes y que eligieron la opción 3.