为什么变量在case语句中不是本地的?

时间:2010-11-05 07:26:53

标签: java

我最近在android java应用程序中添加了另一个菜单项,并且很惊讶Eclipse说来自前一个案例的变量:break不是本地的(所以我刚刚添加了一个后缀来获取)。

在我的脑海里,我有点困惑,第一组案例:如果选择了第二个选项,就不会执行中断。有人可以解释我的错误思考吗?

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

6 个答案:

答案 0 :(得分:12)

你是对的,最多会执行一次,但是一个案例不会创建一个新的范围。您可以手动创建具有自己范围的块。

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

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

答案 1 :(得分:10)

与在C中一样,在Java中,switch语句并不是人们在查看它时所期望的。无效使得很难理解未创建范围。这一切都归结为C,其中一个开关只是语法糖。编译器将开关转换为许多条件跳转。这使得语言能够使用直通,这是在C的设计期间的特征(“中断”仍然是可选的)。此Java功能仍与C兼容。

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

被翻译成

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

答案 2 :(得分:4)

其他人已经解释了你应该做什么,这是一个Java语言的东西,而不是Android特定的东西。

至于为什么以这种方式定义Java语言,我没有想到一个完全合乎逻辑的理由。我能想到的最好的是,如果switch语句的每个case列表都隐式定义了一个范围,那么下面的内容很容易被误读:

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

至少在范围界定的当前定义中,所有可能令人困惑的用法都会导致编译错误。

(IMO,最好避开switch语句中的案例漏洞......就像C#一样。但是这样的设计错误更容易在后见之明发现,并且一旦制作就很难纠正。)

答案 3 :(得分:3)

Matthew是对的 - 整个switch语句对于在其中直接声明的任何变量都有一个范围。根据Matthew的回答,你可以添加更多大括号 - 但将方案体作为方法添加几乎肯定会更好。看起来他们正在做很多事情,不能像那样“内联”。

请注意,此处的范围规则并非特定于Android - 它们是Java的范围规则。

答案 4 :(得分:1)

因为你不应该在那里写很多代码/逻辑 - 把它们分解成方法。

答案 5 :(得分:1)

除了其他答案之外:这里是java language definition

的解释
  

每当控制流进入块 [...]时,就会为在该块中立即包含的局部变量声明语句中声明的每个局部变量创建一个新变量[...]当执行块[...] 时,局部变量实际上不再存在。

局部变量范围是块({ ... }),其中包含内部块。代码中的实际块是在switch语句之后开始的块。