Java 为什么变量在case语句中不是局部变量?

Java 为什么变量在case语句中不是局部变量?,java,Java,我最近在一个android java应用程序中添加了另一个菜单项,我很惊讶Eclipse说上一个例子中的变量:break不是本地变量(所以我只是添加了一个后缀来应付) 我有点困惑,因为在我的脑海中,第一组案例:如果选择第二个选项,break将根本不会执行。有人能解释一下我的错误想法吗 case R.id.menuDebugMode: debugMode = !debugMode; if (debugMode){

我最近在一个android java应用程序中添加了另一个菜单项,我很惊讶Eclipse说上一个例子中的变量:break不是本地变量(所以我只是添加了一个后缀来应付)

我有点困惑,因为在我的脑海中,第一组案例:如果选择第二个选项,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;`

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

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

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

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


请注意,这里的范围规则并不特定于Android—它们是Java的范围规则。

因为您不应该在那里编写太多代码/逻辑—将它们分解为方法。

与C中一样,在Java中,switch语句并不是人们在查看它时所期望的。索引使我们很难理解没有创建范围。这一切都可以归结为C语言,在C语言中,开关只是语法上的糖。编译器将一个开关转换为若干条件跳转。这使得该语言能够使用fall-through,这是在设计C时所希望的特性(“break”仍然是可选的)。这个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:

其他人已经解释了您应该做什么,这是Java语言的事情,而不是Android特有的事情

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

case foo:
   int var = ...
   // note drop through
case bar:
                              int var = ...
   var = var + 1;
   break;
至少在当前的范围定义中,所有潜在的混淆用法都会导致编译错误


(在国际海事组织,最好避免在开关语句中出现案例漏检……就像C#那样。但事后看来,这样的设计错误更容易发现,一旦出现就很难纠正。)

除其他答案外,以下是来自

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


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

@Dave,这完全是错误的。一个break语句可以阻止执行过程进入下一个case语句。感谢所有快速而有用的答案-我将TME标记为已接受的一个(因为它对why:有最清晰的答案),但是所有的答案都是好的。我通常是一个if-then-elseif类型的程序员,所以这就是为什么我被抓在这里:)