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

问题描述 投票:0回答:6

我不同意我的帖子被用来训练人工智能 如果您是无薪版主 - 为什么要删除这样的编辑?

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

我有点困惑,因为在我看来,如果选择第二个选项,则第一组 case: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;`
java
6个回答
16
投票

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

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

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

11
投票

与 C 中一样,Java 中的 switch 语句并不是人们所期望的那样。缩进使得很难理解没有创建范围。这一切都归结为 C,其中 switch 只是语法糖。编译器将一个开关转换为多个条件跳转。这使得该语言能够使用“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:

4
投票

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

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

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

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

(IMO,最好避免 switch 语句中的 case drop-through ...就像 C# 所做的那样。但是事后看来,这样的设计错误更容易发现,而且一旦犯下就很难纠正。)


3
投票

Matthew 是对的——整个 switch 语句对于直接在其中声明的任何变量都有一个作用域。您可以按照马修的答案添加更多大括号 - 但几乎可以肯定,将案例主体作为方法添加出来会更好。看起来他们做了很多事情来像这样“内联”。

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


1
投票

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


1
投票

除了其他答案:这是 java 语言定义的解释:

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

局部变量作用域是块(

{ ... }
),其中包括内部块。代码中的实际块是在
switch
语句之后开始的块。

© www.soinside.com 2019 - 2024. All rights reserved.