2011-01-20 14 views
26

Tengo un problema en mi instrucción de conmutador/caso. El error dice: "Las expresiones de caso deben ser expresiones constantes". Entiendo el error y puedo resolverlo usando If pero alguien me puede decir por qué la expresión de caso debe ser constante en un interruptor/caso. Un ejemplo de código de mi error:Problema de un conmutador Java: las expresiones de caso deben ser expresiones constantes

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 por su explicación !!

+5

¿Por qué utiliza 'findViewById() GetItemID()'.? Si ya tiene la identificación, ¡no necesita obtener el artículo para obtener la identificación! –

+2

las declaraciones del interruptor son un mal olor ... Te recomiendo que estudies el uso del polimorfismo o el patrón del adaptador para lograr un mejor código. Además, puedes evitar problemas como estos por completo. – Bnjmn

+0

@Bnjmn Estoy de acuerdo, especialmente cuando la condición se repite con bastante frecuencia. Si lo usa pocas veces, puede estar bien. Además, lo uso a veces con polimorfismo para crear la instancia concreta inicial. – OscarRyz

Respuesta

54

Por lo tanto, puede ser evaluado durante la fase de compilación (estáticamente cheque)

Ver: http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11 para una definición formal de la switch.

Además, puede ayudar a comprender mejor la forma en que switch se transforma en código de bytes:

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; 
    } 
    } 
} 

Y después de compilar:

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 

} 

Ver que la línea marcada como 1:

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

Evalúa el valor y va a som e otra línea. Por ejemplo, si el valor es 9 saltará a la instrucción 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 

Que a su vez salta a la instrucción 58:

58: return 

Todo esto no sería posible si se evaluó de forma dinámica. Es por eso.

+0

Gracias hombre, que es una respuesta agradable.Entonces, si compila con javap, ¿puedo ver el bytecode generado? – Dimitri

+1

@Dimitri. De nada. 'javap' es otra herramienta (como javadoc o jar) que es el dissamblador java predeterminado. Si se invoca con '-c', verá estas instrucciones. – OscarRyz

+0

Ok. Pero estaba pensando, ¿crees que el bytecode generado en la JVM es el mismo en Dalvik Machine (Android)? Estoy trabajando en Android como lo pueden ver – Dimitri

3

El idDirectory y otros deben ser una constante y no una variable declarada. Switch no funcionará en este caso, necesita cambiar a if-else construir.

EDIT Veo lo que significa OP. Así es como funciona el interruptor en lenguaje Java.

+0

Este es exactamente su problema. Si no puede evitar esto con constantes solo use una configuración algo más compleja if-then-else-if-blah-blah. –

+7

-1 Para responder a lo que el PO ya se sabe: * entiendo el error y puedo resolverlo a través de Si, pero puede que alguien me dice por qué la expresión caso debe ser constante en un interruptor/caja * – OscarRyz

Cuestiones relacionadas