traduction - ¿Por qué un compilador de Java no produce un error de declaración inalcanzable para una declaración entonces inalcanzable?
unreachable statement java que significa (5)
Si trato de compilar
for(;;)
{
}
System.out.println("End");
El compilador de Java produce un error que dice
Unreachable statement
.
Pero si agrego otra declaración de
break
"
inalcanzable
" (según yo) y la hago:
for(;;)
{
if(false) break;
}
System.out.println("End");
Se compila. ¿Por qué no produce un error?
Básicamente, el
código inalcanzable
se detecta analizando el programa de
forma estática
sin
ejecutar realmente el código.
Mientras que la condición se verificará en
tiempo
de
ejecución
.
Entonces, cuando se lleva a cabo este análisis, en realidad no tiene en cuenta la condición, sino que simplemente verifica ese
break;
es accesible (
accesible
) a través de
if
.
Como se explicó en
mi respuesta a una pregunta similar
, la construcción específica
if(compile-time-false)
está exenta de las reglas de inalcanzabilidad como una puerta trasera explícita.
En este caso, el compilador trata su
break
como accesible debido a eso.
De la JLS
Una instrucción if-then puede completarse normalmente si al menos uno de los siguientes es verdadero:
> La instrucción if-then es accesible y la expresión de condición no es una expresión constante cuyo valor es verdadero.
> La instrucción then puede completarse normalmente.
Entonces,
if(false)
está permitido.
Esta capacidad de "compilar condicionalmente" tiene un impacto significativo y una relación con la compatibilidad binaria. Si se compila un conjunto de clases que usan dicha variable "flag" y se omite el código condicional, no es suficiente distribuir solo una nueva versión de la clase o interfaz que contenga la definición del flag. Un cambio en el valor de un indicador no es, por lo tanto, compatible con los binarios preexistentes. (También hay otras razones para tal incompatibilidad, como el uso de constantes en las etiquetas de caso en las declaraciones de cambio;)
El comportamiento se define en la descripción JLS de declaraciones inalcanzables :
La declaración then es accesible si la declaración if-then es accesible.
Por lo tanto, el compilador determina que la instrucción then (
break;
) es accesible, independientemente de la condición en el
if
.
Y un poco más, énfasis mío:
Un enunciado básico
for
puede completarse normalmente si al menos uno de los siguientes es verdadero:
- La declaración for es accesible, hay una expresión de condición, y la expresión de condición no es una expresión constante (§15.28) con valor verdadero.
- Hay una declaración de
break
accesible que sale de la declaración for.
Por lo tanto, el for puede completarse normalmente porque la instrucción then contiene un
break
.
Como notó, no funcionaría si reemplazara el
break
con el
return
.
La justificación se explica hacia el final de la sección.
En sustancia,
if
tiene un tratamiento especial para permitir construcciones como:
if(DEBUG) { ... }
donde DEBUG puede ser una constante de tiempo de compilación.
La razón principal por la que Java no detecta todas las declaraciones inalcanzables es que generalmente es imposible responder si el código es accesible o no. Esto se deduce del hecho de que el problema de detención es indecidible sobre las máquinas Turing.
Entonces, está claro que no se pueden detectar todas las declaraciones inalcanzables, pero ¿por qué no intentar evaluar las condiciones?
Imagine ahora que la condición utilizada no es solo
false
sino algo así como
~x == x
.
Por ejemplo, todas estas declaraciones se imprimirán
true
para cada
int x
(
source
).
System.out.println((x + x & 1) == 0);
System.out.println((x + -x & 1) == 0);
System.out.println((-x & 1) == (x & 1));
System.out.println(((-x ^ x) & 1) == 0);
System.out.println((x * 0x80 & 0x56) == 0);
System.out.println((x << 1 ^ 0x1765) != 0);
Las declaraciones pueden ser bastante complicadas; lleva tiempo resolverlos. Aumentaría significativamente el tiempo de compilación y, después de todo, no detectará todas las declaraciones inalcanzables. El compilador fue diseñado para tomar algunos esfuerzos pero no gastar demasiado tiempo para eso.
La única pregunta que queda es: ¿dónde dejar de resolver las condiciones? Las razones para eso no parecen tener justificación matemática y se basan en el escenario de uso. JLS-14.21 explica los motivos de su caso particular.