2010-11-05 10 views
9

Recientemente agregué otro elemento del menú a una aplicación java de Android y me sorprendió que Eclipse dijera esa variable del caso anterior: el corte no era local (así que acabo de agregar un sufijo para salir adelante).¿Por qué las variables no son locales en las sentencias de caso?

Estoy un poco confundido ya que en mi opinión, el 1er conjunto de casos: break no se ejecutaría en absoluto si se eligió la 2ª opción. ¿Podría alguien explicar mi pensamiento defectuoso por favor?

 case R.id.menuDebugMode: 
      debugMode = !debugMode; 
      if (debugMode){ 
       Toast.makeText(mainActivity.this, "Debug Mode on - NOT TO BE USED WHILST DRIVING", Toast.LENGTH_LONG).show();   
      } else { 
       tvDebug.setText(""); 
       tvInfo.setText(""); 
      } 
      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); 
      SharedPreferences.Editor editor = settings.edit(); 
      editor.putBoolean("debugMode", debugMode); 
      editor.commit(); 
     break; 

     case R.id.menuSpeedMode: 
      speedSignMode = !speedSignMode; 
      if (speedSignMode){ 
       Toast.makeText(mainActivity.this, "SpeedSign Mode in use", Toast.LENGTH_LONG).show();   

      } else { 
        Toast.makeText(mainActivity.this, "MapSpeed Mode in use", Toast.LENGTH_LONG).show();    
      } 
      SharedPreferences settings2 = getSharedPreferences(PREFS_NAME, 0); 
      SharedPreferences.Editor editor2 = settings2.edit(); 
      editor2.putBoolean("speedSignMode", speedSignMode); 
      editor2.commit(); 
     break;` 
+0

Gracias por todas las respuestas rápidas y útiles - Marqué a TME como el aceptado (ya que tenía la esencia clara del por qué :) pero todas las respuestas fueron buenas. Normalmente soy un programador tipo if if else else, por eso me han pillado aquí :) – SimpleSi

Respuesta

9

Al igual que en C, en Java una instrucción de conmutación no es lo que uno esperaría al mirarla. La introducción dificulta comprender que no se crea un alcance. Todo esto se reduce a C, donde un cambio es simplemente azúcar sintáctica. El compilador transforma un interruptor en una serie de saltos condicionales. Esto permite que el lenguaje utilice la función de caída, una característica que se diseñó durante el diseño de C ("pausa" sigue siendo opcional). Esta característica de Java se mantuvo compatible con C.

switch(a): 
    case 1: 
     dosomething(); 
    case 2: 
     dosomemore(); 

se traduce en

if(a==1) jump ##1; 
if(a==2) jump ##2; 
jump ##3; 
##1: 
dosometing(); 
##2: 
dosomemore(); 
##3: 
12

Tiene razón de que se ejecutará como máximo uno, pero un caso no crea un nuevo ámbito. Puede crear manualmente un bloque con su propio alcance.

case foo: 
    { 
     int var = ... 
    } 
    break; 

case bar: 
    { 
     int var = ... 
    } 
    break; 
+2

@Dave, eso está simplemente mal. Una declaración de interrupción detiene la ejecución que cae a la siguiente declaración de caso. – SimonC

3

Matthew tiene razón: toda la instrucción switch tiene un alcance para cualquier variable declarada directamente dentro de ella. Usted puede agregue más llaves según la respuesta de Matthew, pero seguramente sería mejor extramar los cuerpos de la caja como métodos. Parece que están haciendo bastante para ser incluidos "en línea" de esa manera.

Tenga en cuenta que las reglas de alcance aquí no son específicas de Android: son las reglas de alcance de Java.

1

Como se supone que no debe escribir mucho código/lógica, desglose estos métodos.

4

Otros han explicado lo que debe hacer, y que esto es una cosa lenguaje Java, no es una cosa específica Android.

En cuanto a por qué el lenguaje Java se define de esta manera, no he encontrado una razón completamente lógica. Lo mejor que puedo pensar es que si cada una de las listas de casos de una sentencia switch definido implícitamente un ámbito, a continuación, el siguiente podría ser fácilmente malinterpretado:

case foo: 
    int var = ... 
    // note drop through 
case bar: 
           int var = ... 
    var = var + 1; 
    break; 

Al menos con la actual definición del alcance, todos los usos potencialmente confusos resultan en errores de compilación.

(IMO, hubiera sido mejor evitar la exclusión de mayúsculas/minúsculas en instrucciones de conmutación ... al igual que C#. Pero errores de diseño como estos son mucho más fáciles de detectar en retrospectiva, y son difíciles de corregir una vez hecho.)

1

En sirvieron a las otras respuestas: aquí está la explicación de la java language definition:

Siempre que el flujo de control entra en un bloque de [...], se crea una nueva variable para cada variable local declarada en una declaración de declaración de variable local contenida inmediatamente dentro de ese bloque [...] La variable local effec tivamente deja de existir cuando la ejecución del bloque [...] está completo.

Un ámbito de variable local es el bloque ({ ... }), que incluye bloques internos. El bloque real en su código es el bloque que comienza después de la instrucción switch.

Cuestiones relacionadas