2015-09-10 18 views
21

adottare le seguenti frammento di codice Java:(Compiler) else if (true) vs scenario altrimenti

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

Quello che mi chiedevo è come le offerte del compilatore con questo. Non sarebbe logico che il compilatore rimuovesse completamente l'istruzione else if(true) per non dover eseguire un controllo, anche se è codificato come vero. In particolare in Eclipse, come viene interpretato il codice sopra?

O che dire nel seguente scenario:

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

Non sarebbe logico in questo caso per il compilatore per rimuovere l'istruzione else? Perché mentre è in esecuzione, l'istruzione else non è raggiungibile.

+0

Basta chiedersi ... il più logico (o almeno il più efficiente) sarebbe il compilatore di lasciare solo il 'metodo di lancio A', in entrambi i casi. – brlaranjeira

+0

"Non sarebbe logico ..." Sì, ed è quello che fanno in realtà i compilatori più moderni. –

risposta

19

Le istruzioni non raggiungibili sono vietate in Java e devono provocare errori di compilazione. Il JLS definisce cosa è un bilancio d'irraggiungibili: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21

E 'troppo lunga per essere interamente citato qui, ma qui è un estratto (enfasi mio):

if (false) { x=3; } 

non si traduca in un errore in fase di compilazione. Un compilatore di ottimizzazione può realizzare che l'istruzione x = 3; non verrà mai eseguito e potrebbe scegliere per omettere il codice per tale istruzione dal file di classe generato, ma l'istruzione x = 3; non è considerato "irraggiungibile" nel significato tecnico specificato qui.

Il razionale di questo diverso trattamento è quello di consentire ai programmatori di definiscono "variabili flag" quali:

static final boolean DEBUG = false; 

e poi scrivere codice come:

if (DEBUG) { x=3; } 

L'idea è che si dovrebbe essere possibile modificare il valore di DEBUG da falso a vero o da vero a falso e quindi compilare correttamente il codice senza altre modifiche al testo del programma.

Quindi la risposta dipenderà dal compilatore che si utilizza e dalle sue opzioni di ottimizzazione.

+2

Al di là di questo, sarebbe piuttosto noioso se un programmatore che ha una variabile come 'staticLogging statico booleano ', che in realtà * viene usato come variabile *, non possa successivamente cambiarlo in' statico finale booleano elableLogging = false; 'senza avere per modificare manualmente tutto il codice che lo legge. – supercat

2

Informazioni su Eclipse, in particolare, ti avvertiranno che l'ultimo blocco non è raggiungibile, ma la compilazione è delegata al tuo jdk, quindi forse è il compilatore a cosa avverte Eclipse.

+3

In realtà, Eclipse ha il proprio compilatore, 'ecj' (Eclipse Compiler for Java). Il 'javac' di Sun/Oracle (scritto da Martin Odersky, il designer di Scala) è un compilatore batch, non progettato per un uso interattivo e incrementale. 'ecj' (come tutto l'Eclipse) è derivato da IBM VisualAge per Smalltalk, e quindi specificamente progettato per la compilazione incrementale interattiva" while-you-type "all'interno di un IDE. –

3

Non c'è una risposta particolare a questa domanda. Dipende dal compilatore Java. La maggior parte dei compilatori ignora il codice guasto perché non cambierà la semantica del codice anche se risulta in un file di classe più grande.

Se sei interessato a questa analisi, c'è molta letteratura sull'eliminazione del codice morto.

3

Si può provare a scrivere il codice e decompilare il file di classe. Il mio compilatore ottimizza

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

come

else { 
///launch methodA 
} 

e

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

come

else { 
///launch methodA 
} 

Credo che tutte le versioni di compilatore di ottimizzare in questo modo.

10

Il compilatore optmizes è in fase di compilazione:

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

Mi dà (con la mia 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 
} 

Il codice stampa semplicemente Hello. Boom non è nemmeno considerato.

Tutti i più recenti compilatori Java eliminano il codice morto al momento della compilazione.

2

Ora scrivo il codice in Eclipse mio metodo

 public static void aa(String b){ 
     if (true) { 

     } 

     else if (true) { 
      System.out.println("asas"); 
     } else { 

     } 
     } 

Dopo che ho compilato il mio codice e ho decompilatore il mio codice con il codice JD-GUI.My decompilatore è:

public static void aa(String b) {} 

}

risultato è molto buono :)

1

Wouldn È logico che il compilatore rimuova l'istruzione else if (true) al fine di non dover eseguire un controllo, anche se è codificato come vero.

No, non lo sarebbe, a meno che entrambi i blocchi avessero lo stesso contenuto, e perché dovrebbe controllarlo? Sarebbe semanticamente scorretto. Sarebbe logico che il compilatore rimuova l'ultimo irraggiungibile else, e questo è ciò che fa.