java if-statement compiler-construction language-lawyer

java - (Compilador) else if(verdadero) vs else escenario



s if (8)

Tome el siguiente fragmento de código Java:

.... else if (true){ //hard-coded as true ///launch methodA } else { ///launch methodA (same code as in the ` else if ` statement) } ....

Lo que me preguntaba es cómo el compilador lidia con esto. ¿No sería lógico que el compilador elimine por completo la sentencia else if(true) para no tener que realizar una comprobación, aunque esté codificada como verdadera? Específicamente en Eclipse, ¿cómo se interpreta el código anterior?

O qué tal en el siguiente escenario:

.... else if (true){ //hard-coded as true ///launch methodA } else { ///launch methodBB } ....

¿No sería lógico en este caso que el compilador elimine la instrucción else ? Porque mientras se ejecuta, la instrucción else es inalcanzable.


¿No sería lógico que el compilador elimine por completo la sentencia else if (true) para no tener que realizar una comprobación, aunque esté codificada como verdadera?

No, no lo haría, a menos que ambos bloques tuvieran el mismo contenido, y ¿por qué verificaría eso? Sería semánticamente incorrecto. Lo lógico sería que el compilador elimine el último inalcanzable else , y eso es lo que hace.


Acerca de Eclipse en particular, va a advertirte que el último bloque es inalcanzable, pero la compilación se delega a tu jdk, así que tal vez sea el compilador el que advierte a Eclipse.


Ahora escribo códigos en eclipse, mi método es

public static void aa(String b) { if (true) { } else if (true) { System.out.println("asas"); } else { } }

Después de compilar mi código y descompilar mi código con JD-GUI. Mi código descompilado es:

public static void aa(String b) {}

el resultado es muy bueno!


El compilador lo optmiza en tiempo de compilación:

public class Test { public static void main(String[] args) { if(true) { System.out.println("Hello"); } else { System.out.println("Boom"); } }

Me da (con mi Java 1.8.0_45 ):

Compiled from "Test.java" public class Test { publicTest(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String Hello 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }

El código simplemente imprime Hello . Boom ni siquiera se considera.

Todos los compiladores recientes de Java eliminan el código muerto en tiempo de compilación.


Las declaraciones inalcanzables están prohibidas en Java y deben desencadenar errores de compilación. El JLS define lo que es una declaración inalcanzable: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21

Es demasiado largo para ser citado por completo aquí, pero aquí hay un extracto (el énfasis es mío):

if (false) { x=3; }

no da como resultado un error en tiempo de compilación. Un compilador de optimización puede darse cuenta de que la declaración x = 3; nunca se ejecutará y puede optar por omitir el código para esa declaración 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 programadores 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 compilar el código correctamente sin ningún otro cambio en el texto del programa.

Entonces, la respuesta dependerá del compilador que use y sus opciones de optimización.


No hay una respuesta particular a esta pregunta. Depende del compilador de Java. La mayoría de los compiladores ignoran Dead Code porque no cambiará la semántica del código, incluso si resulta en un archivo de clase más grande.

Si está interesado en dicho análisis, hay mucha literatura sobre la eliminación del Código Muerto.


Puede intentar escribir el código y descompilar el archivo de clase. Mi compilador optimiza

else if (true){ //hard-coded as true ///launch methodA } else { ///launch methodA (same code as in the else if statement) }

como

else { ///launch methodA }

y

else if (true){ //hard-coded as true ///launch methodA } else { ///launch methodBB }

como

else { ///launch methodA }

Creo que todas las versiones del compilador lo optimizarán de esta manera.


Respuestas relacionadas: Java If (false) Compilar

Consulte especialmente las observaciones sobre el uso de javap -c para diagnosticar bytecode para ver si el código muerto en realidad fue eliminado. https://.com/a/6240017/679457