java try-catch

java - Código inalcanzable funcionando bien-¿Cómo?



try-catch (4)

Creo que estas son las citas relevantes de JLS 14.21 :

  • Un bloque vacío que no es un bloque de interruptor puede completarse normalmente si es alcanzable.

    Un bloque no vacío que no sea un bloque de conmutación puede completarse normalmente si la última declaración puede completarse normalmente.

    La primera declaración en un bloque no vacío que no sea un bloque de conmutación es accesible si se puede acceder al bloque.

    Se puede acceder a cualquier otra declaración S en un bloque no vacío que no sea un bloque de conmutación si la instrucción que precede a S puede completarse normalmente .

Entonces tus

System.out.println("I am unreachable??!!!");

La declaración es accesible si if (que significa "si y solo si") la declaración de prueba puede completarse normalmente, lo que lleva a la siguiente cita:

  • Una declaración de prueba puede completarse normalmente si se cumplen las dos condiciones siguientes :

    • El bloque try puede completarse normalmente o cualquier bloque catch puede completarse normalmente .

    • Si la instrucción try tiene un bloque finally, entonces el bloque finally puede completarse normalmente .

Ya que su bloque catch puede completarse normalmente y usted tiene un bloque finally que puede completarse normalmente, la instrucción try puede completarse normalmente. De ahí el System.out.println("I am unreachable??!!!"); la declaración que sigue se considera accesible, independientemente de la return; Enunciado dentro del bloque try .

Tenga en cuenta el or en

El bloque try puede completarse normalmente o cualquier bloque catch puede completarse normalmente.

Esto requiere que el bloque try o al menos uno de los bloques catch se completen normalmente. No requiere tanto el bloque try bloque catch para completarse normalmente.

Finalmente, la lógica detrás de este comportamiento:

El compilador no debe analizar si un bloque try puede o no lanzar una Exception . La razón es que la jerarquía de la clase de Exception incluye excepciones marcadas y no verificadas, y las excepciones no verificadas no se declaran en cláusulas de throws (si reemplazó la Exception con alguna excepción marcada, como IOException , el compilador se quejaría de que su bloque try nunca lanza esa excepción) , lo que haría el bloque catch inalcanzable).

Por lo tanto, dado que tiene un bloque catch (Exception e) que puede completarse normalmente, el compilador asume que este bloque catch es alcanzable y, por lo tanto, toda la instrucción try puede completarse normalmente, incluso aunque el bloque try no pueda completarse normalmente.

El bloque finally, si está presente, también debe poder completarse normalmente, ya que el bloque finally también se ejecuta, por lo que si no pudiera completarse normalmente, la instrucción try completa no podría completarse normalmente.

Según tengo entendido, el código que he escrito no debe compilarse, ya que la declaración "No se puede acceder" aparece después de la return .

Sin embargo, está compilando absolutamente bien.

También desde el JLS: Declaraciones inalcanzables que no debe compilar.

de la especificación, en 14.21 Declaraciones inalcanzables:

Una declaración de prueba puede completarse normalmente si se cumplen las dos condiciones siguientes:

  • El bloque try puede completarse normalmente o cualquier bloque catch puede completarse normalmente.

  • Si la instrucción try tiene un bloque finally, entonces el bloque finally puede completarse normalmente.

Aquí el bloque try no puede completarse normalmente, pero el bloque catch puede hacerlo tan bien como el bloque finally, así que estoy confundido aquí

public class Test1 { public static void main(String[] args) { try { return; } catch (Exception e) { System.out.println("catch"); } finally { System.out.println("finally"); } System.out.println("I am unreachable??!!!"); } }

¿Puede alguien ayudarme a entender este comportamiento?


Cuando miras las "declaraciones inalcanzables" en un programa Java, lo que cuenta es lo que dice la definición en el idioma, no lo que un compilador inteligente podría descubrir.

De acuerdo con el lenguaje Java, la última impresión no es una declaración inalcanzable. Aunque al mirar el código es fácil (para un humano inteligente) darse cuenta de que nunca se puede ejecutar.

Un lenguaje de programación necesita confiar en reglas fijas que sean fáciles de seguir para el compilador. Un compilador no puede confiar en la inteligencia, porque los compiladores diferentes tendrían diferentes cantidades de inteligencia, por lo que si no siguieran las reglas simples y fijas, algunos compiladores encontrarían la afirmación inalcanzable y otros no.


Has vuelto en el intento.

¿Qué pasa si hay una excepción y va directamente a la captura. Por lo tanto, no es inalcanzable en términos de compilador y se está compilando con éxito.

La compilación fallará si usted también tendrá retorno en la captura

También, según JLS 14.21 :

Una instrucción break alcanzable sale de una instrucción si, dentro del objetivo de break, o bien no hay declaraciones try cuyos bloques try contienen la instrucción break, o hay declaraciones try cuyos bloques try contienen la instrucción break y todas las cláusulas finalmente de esas declaraciones try pueden completarse normalmente.

Vea la salida a continuación cuando haya regresado en ambos intentos y capturas:

jshell> public class Test1 { ...> public static void main(String[] args) { ...> try { ...> return; ...> ...> } catch (Exception e) { ...> return; ...> ...> } ...> ...> System.out.println("I am unreachable??!!!"); ...> } ...> } | Error: | unreachable statement | System.out.println("I am unreachable??!!!"); | ^------------------------------------------^

Similar será el caso cuando haya regresado en su sentencia finally y la compilación fallará.

Se considerará que se puede alcanzar una declaración posterior al intento si:

1) Try has a return statement with catch and finally not having return statement 2) Try does not have a return statement with catch having or not having return statement and finally not having return statement 3) Try, catch and finally not having return statement


Tratando de dar una razón más simplificada para el problema, el código es accesible, en caso de que ocurra una excepción en el bloque try. En ese caso, el control va más allá al bloque de captura y luego al bloque final. Después de finalmente bloquear, se ejecutará la declaración particular.

try { return; //line 1 } catch (Exception e) { System.out.println("catch"); //line 2 } finally { System.out.println("finally"); //line 3 } System.out.println("I am unreachable??!!"); //line 4

Eso significa que hay 2 casos, por lo tanto 2 flujos:

  1. línea 1 -> línea 3 -> retorno (en caso de que no haya una excepción)
  2. línea 1 (se produce una excepción) -> línea 2 -> línea 3 -> línea 4 (en caso de que intente obtener una excepción)

La línea se volverá inalcanzable, solo si no dejamos ninguna posibilidad en la que el control vaya allí. Hay 2 formas de hacerlo:

  1. regreso del bloque de captura
  2. Regreso del bloque finalmente.

En ambos casos, el control nunca puede fluir a esa línea.

try { return; //line 1 } catch (Exception e) { System.out.println("catch"); //line 2 return; //return control } finally { System.out.println("finally"); //line 3 return; //or return from here } System.out.println("I am unreachable??!!"); //line 4

Espero que ahora proporcione una imagen clara de la razón real del problema.