2011-01-20 16 views
26

Ho un problema nella mia istruzione switch/case. L'errore dice: "Le espressioni del caso devono essere espressioni costanti". Comprendo l'errore e posso risolverlo usando If, ma qualcuno può dirmi perché l'espressione del caso deve essere costante in un interruttore/caso. Un esempio di codice del mio errore:A Cambia problema Java: le espressioni del caso devono essere espressioni costanti

public boolean onOptionsItemSelected(MenuItem item) { 
    int idDirectory = ((MenuItem) findViewById(R.id.createDirectory)).getItemId(); 
    int idSuppression = ((MenuItem) findViewById(R.id.recycleTrash)).getItemId(); 
    int idSeeTrash = ((MenuItem) findViewById(R.id.seeTrash)).getItemId(); 

    switch (item.getItemId()) { 
    case idDirectory: 
     createDirectory(currentDirectory); 
     break; 
    case idSuppression: 
     recycleTrash(); 
     break; 
    case idSeeTrash: 
     seeTrash(); 
     break; 
    } 

    return super.onOptionsItemSelected(item); 
} 

Thx per la tua spiegazione !!

+5

Perché stai usando 'findViewById() getItemId()'.? Se hai già l'id, non è necessario ottenere l'oggetto per ottenere l'id! Le dichiarazioni dei commutatori –

+2

sono di cattivo odore ... Vi consiglio di utilizzare il polimorfismo o il modello dell'adattatore per ottenere un codice migliore. Inoltre puoi evitare del tutto problemi come questi. – Bnjmn

+0

@Bnjmn Sono d'accordo, specialmente quando la condizione si ripete abbastanza spesso. Se lo si utilizza raramente, potrebbe essere ok. Inoltre, a volte lo uso con il polimorfismo per creare l'istanza concreta iniziale. – OscarRyz

risposta

54

Così può essere valutata durante la fase di compilazione (controllare staticamente)

See: http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11 per una definizione formale del switch.

Inoltre può aiutare a capire meglio come che switch si trasforma in bytecode:

class Switch { 
    void x(int n) { 
    switch(n) { 
     case 1: System.out.println("one"); break; 
     case 9: System.out.println("nine"); break; 
     default: System.out.println("nothing"); break; 
    } 
    } 
} 

E dopo la compilazione:

C:\>javap -c Switch 
Compiled from "Switch.java" 
class Switch extends java.lang.Object{ 
Switch(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

void x(int); 
    Code: 
    0: iload_1 
    1: lookupswitch{ //2 
       1: 28; 
       9: 39; 
       default: 50 } 
    28: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    31: ldc  #3; //String one 
    33: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    36: goto 58 
    39: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    42: ldc  #5; //String nine 
    44: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    47: goto 58 
    50: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    53: ldc  #6; //String nothing 
    55: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    58: return 

} 

Vedere quella linea contrassegnato come 1:

1: lookupswitch{ //2 
      1: 28; 
      9: 39; 
      default: 50 } 

Valuta il valore e passa a som e altra linea. Per esempio se il valore è 9 salterà per l'istruzione 39:

39: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    42: ldc  #5; //String nine 
    44: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    47: goto 58 

Che a sua volta salti per l'istruzione 58:

58: return 

Tutto questo non sarebbe stato possibile se è stata valutata in modo dinamico. Ecco perchè.

+0

Grazie amico, questa è una bella risposta.Quindi, se compilato con javap, posso vedere il bytecode generato ?? – Dimitri

+1

@Dimitri. Prego. 'javap' è un altro strumento (come javadoc o jar) che è il java dissambler predefinito. Se invocato con '-c' vedrai queste istruzioni. – OscarRyz

+0

Ok. Ma stavo pensando, pensi che il bytecode generato nella JVM sia lo stesso in Dalvik Machine (Android). Sto lavorando su Android come potresti vederlo. – Dimitri

3

Il idDirectory e altri devono essere una variabile costante e non dichiarata. Switch non funzionerà in questo caso, è necessario passare al costrutto if-else.

EDIT Vedo cosa significa OP. Questo è il modo in cui l'interruttore funziona in linguaggio java.

+0

Questo è esattamente il tuo problema. Se non riesci ad aggirare questo problema con le costanti usa solo un setup un po 'più complesso di if-then-else-if-blah-blah. –

+7

-1 Per rispondere a ciò che l'OP sa già: * Comprendo l'errore e posso risolverlo usando If, ma qualcuno può dirmi perché l'espressione del caso deve essere costante in un interruttore/caso * – OscarRyz

Problemi correlati