¿Por qué Java tiene un error de comstackdor de “statement inalcanzable”?

A menudo encuentro que al depurar un progtwig es conveniente (aunque podría decirse que una mala práctica) insertar una statement de devolución dentro de un bloque de código. Podría intentar algo como esto en Java …

class Test { public static void main(String args[]) { System.out.println("hello world"); return; System.out.println("i think this line might cause a problem"); } } 

por supuesto, esto produciría el error del comstackdor.

Test.java:7: statement inalcanzable

Pude entender por qué una advertencia podría justificarse porque tener un código sin usar es una mala práctica. Pero no entiendo por qué esto necesita generar un error.

¿Es solo Java tratando de ser una niñera, o hay una buena razón para hacer de esto un error de comstackción?

Porque el código inalcanzable no tiene sentido para el comstackdor. Si bien hacer código significativo para las personas es primordial y más difícil que hacerlo significativo para un comstackdor, el comstackdor es el consumidor esencial de código. Los diseñadores de Java toman el punto de vista de que el código que no es significativo para el comstackdor es un error. Su postura es que si tiene algún código inalcanzable, ha cometido un error que debe corregirse.

Aquí hay una pregunta similar: Código inalcanzable: ¿error o advertencia? , en el que el autor dice “Personalmente, creo firmemente que debería ser un error: si el progtwigdor escribe un código, siempre debe ser con la intención de ejecutarlo en algún escenario”. Obviamente, los diseñadores de lenguaje de Java están de acuerdo.

Si el código inalcanzable debe evitar la comstackción es una pregunta sobre la cual nunca habrá consenso. Pero esta es la razón por la cual los diseñadores de Java lo hicieron.


Varias personas en comentarios señalan que hay muchas clases de código inalcanzable. Java no impide la comstackción. Si entiendo las consecuencias de Gödel correctamente, ningún comstackdor puede atrapar todas las clases de código inalcanzable.

Las pruebas unitarias no pueden detectar todos los errores. No usamos esto como argumento en contra de su valor. Del mismo modo, un comstackdor no puede detectar todos los códigos problemáticos, pero sigue siendo valioso para evitar la comstackción de código incorrecto cuando puede.

Los diseñadores de lenguaje Java consideran que el código inalcanzable es un error. Por lo tanto, es razonable evitar la comstackción cuando sea posible.


(Antes de votar: la pregunta no es si Java debe tener un error de comstackdor de sentencia inalcanzable. La pregunta es por qué Java tiene un error de comstackdor de sentencia inalcanzable. No me rechaces solo porque piensas que Java tomó una decisión de diseño equivocada).

No hay una razón definitiva por la cual las declaraciones inalcanzables no deben permitirse; otros idiomas los permiten sin problemas. Para su necesidad específica, este es el truco habitual:

 if (true) return; 

Parece absurdo, cualquiera que lea el código adivinará que debe haberlo hecho deliberadamente, no un error descuidado de dejar el rest de las declaraciones inalcanzables.

Java tiene un poco de soporte para la “comstackción condicional”

http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.21

 if (false) { x=3; } 

no da como resultado un error en tiempo de comstackción. Un comstackdor de optimización puede darse cuenta de que la statement x = 3; nunca se ejecutará y puede optar por omitir el código para esa statement del archivo de clase generado, pero la instrucción x = 3; no se considera “inalcanzable” en el sentido técnico especificado aquí.

La razón de este tratamiento diferente es permitirles a los progtwigdores definir “variables de bandera” tales como:

 static final boolean DEBUG = false; 

y luego escribe un código como:

 if (DEBUG) { x=3; } 

La idea es que sea posible cambiar el valor de DEPURAR de falso a verdadero o de verdadero a falso y luego comstackr el código correctamente sin ningún otro cambio en el texto del progtwig.

Es Nanny. Siento que .Net acertó: muestra una advertencia de código inalcanzable, pero no un error. Es bueno ser advertido al respecto, pero no veo ninguna razón para evitar la comstackción (especialmente durante las sesiones de depuración en las que es bueno lanzar una devolución para eludir algún código).

Solo me di cuenta de esta pregunta y quería agregar mi $ .02 a esto.

En el caso de Java, esto no es realmente una opción. El error de “código inalcanzable” no proviene del hecho de que los desarrolladores de JVM pensaban proteger a los desarrolladores de nada, o ser más vigilantes, sino de los requisitos de la especificación de JVM.

Tanto el comstackdor de Java como JVM usan lo que se llama “mapas de stack”: una información definitiva sobre todos los elementos de la stack, tal como se asignaron para el método actual. Se debe conocer el tipo de cada ranura de la stack, de modo que una instrucción JVM no maltrate elementos de un tipo para otro tipo. Esto es más importante para evitar que se utilice un valor numérico como puntero. Es posible, mediante el ensamblaje de Java, intentar insertar / almacenar un número, pero luego mostrar / cargar una referencia de objeto. Sin embargo, JVM rechazará este código durante la validación de la clase, es decir, cuando los mapas de stack se creen y se prueben por coherencia.

Para verificar los mapas de stack, la máquina virtual debe recorrer todas las rutas de código existentes en un método y asegurarse de que, independientemente de la ruta de código que se ejecute alguna vez, los datos de la stack para cada instrucción coinciden con lo que haya introducido cualquier código anterior. / almacenado en la stack. Entonces, en caso simple de:

 Object a; if (something) { a = new Object(); } else { a = new String(); } System.out.println(a); 

en la línea 3, JVM comprobará que ambas twigs de ‘si’ solo han almacenado en un (que es simplemente var local 0) algo que es compatible con Object (ya que así es como el código de la línea 3 y on tratará var local 0 )

Cuando el comstackdor llega a un código inalcanzable, no sabe muy bien en qué estado se encuentra la stack en ese punto, por lo que no puede verificar su estado. Ya no puede comstackr el código en ese punto, ya que tampoco puede hacer un seguimiento de las variables locales, por lo que en lugar de dejar esta ambigüedad en el archivo de clase, produce un error fatal.

Por supuesto, una condición simple como if (1<2) engañará, pero no es realmente engañoso: le está dando una twig potencial que puede conducir al código, y al menos tanto el comstackdor como la VM pueden determinar cómo la stack los artículos se pueden usar desde allí en adelante.

PD: No sé qué hace .NET en este caso, pero creo que también fallará la comstackción. Esto normalmente no será un problema para ningún comstackdor de códigos de máquina (C, C ++, Obj-C, etc.)

Uno de los objectives de los comstackdores es descartar clases de errores. Algún código inalcanzable está allí por accidente, es bueno que javac descarte esa clase de error en tiempo de comstackción.

Por cada regla que capte código erróneo, alguien querrá que el comstackdor lo acepte porque sabe lo que está haciendo. Esa es la pena de la verificación del comstackdor, y obtener el equilibrio correcto es uno de los puntos clave del diseño del lenguaje. Incluso con el control más estricto todavía hay una cantidad infinita de progtwigs que se pueden escribir, por lo que las cosas no pueden ser tan malas.

Si bien creo que este error de comstackción es bueno, hay una manera de evitarlo. Use una condición que sepa que será verdadera:

 public void myMethod(){ someCodeHere(); if(1 < 2) return; // compiler isn't smart enough to complain about this moreCodeHere(); } 

El comstackdor no es lo suficientemente inteligente como para quejarse de eso.

Sin duda es bueno quejarse, cuanto más estricto sea el comstackdor, mejor será, siempre que le permita hacer lo que necesita. Por lo general, el pequeño precio a pagar es comentar el código, la ganancia es que cuando comstacks tu código funciona. Un ejemplo general es Haskell acerca de qué personas gritan hasta que se dan cuenta de que su prueba / depuración es solo la prueba principal y la corta. Personalmente, en Java casi no hago ninguna depuración estando (de hecho a propósito) no atento.

Si el motivo para permitir el if (aBooleanVariable) return; someMoreCode; if (aBooleanVariable) return; someMoreCode; es permitir banderas, luego el hecho de que if (true) return; someMoreCode; if (true) return; someMoreCode; no genera un error de tiempo de comstackción parece una inconsistencia en la política de generación de excepción CodeNotReachable, ya que el comstackdor ‘sabe’ que true no es un indicador (no una variable).

Otras dos formas que pueden ser interesantes, pero no se aplican a la desactivación de parte del código de un método, así como a la if (true) return :

Ahora, en lugar de decir if (true) return; es posible que desee decir ” assert false y agregar -ea OR -ea package OR -ea className a los argumentos de jvm. Lo bueno es que esto permite cierta granularidad y requiere agregar un parámetro extra a la invocación de jvm, por lo que no es necesario establecer un indicador DEBUG en el código, sino mediante un argumento adicional en tiempo de ejecución, que es útil cuando el objective no es el la máquina del desarrollador y la recomstackción y transferencia del bytecode lleva tiempo.

También existe el modo System.exit(0) , pero esto podría ser una exageración, si lo coloca en Java en un JSP terminará el servidor.

Además de que Java es un lenguaje de ‘niñera’, prefiero usar algo nativo como C / C ++ para tener más control.