Me topé con un código que se veía así:
void run() {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() {
throw new RuntimeException();
}
Este código me sorprende porque parece que el run()
método-es capaz de arrojar un Exception
, ya que lo atrapa Exception
y luego lo vuelve a arrojar, pero no se declara que el método arroje Exception
y aparentemente no es necesario. Este código se compila muy bien (en Java 11 al menos).
Mi expectativa sería que tendría que declarar throws Exception
en el run()
método-.
Información extra
De manera similar, si doSomething
se declara que se lanza, IOException
entonces solo se IOException
debe declarar en el run()
método-, aunque Exception
se atrape y se vuelva a lanzar.
void run() throws IOException {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() throws IOException {
// ... whatever code you may want ...
}
Pregunta
A Java generalmente le gusta la claridad, ¿cuál es la razón detrás de este comportamiento? ¿Siempre ha sido así? ¿Qué en la especificación del lenguaje Java permite que el run()
método no necesite declarar throws Exception
en los fragmentos de código anteriores? (Si quisiera agregarlo, IntelliJ me advierte que Exception
nunca se tira).
-source 1.6
bandera genera un error de compilación como se esperaba. Compilar con la compatibilidad fuente 7 no no elevar el error de compilación
In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions : 1. 1. The try block is able to throw it. 2. There are no other preceding catch blocks that can handle it. 3. It is a subtype or supertype of one of the catch clause's exception parameters.
javac
: he estado encontrando casos en los que el compilador Eclipse fue más indulgente.