【问题标题】:switch case statement error: case expressions must be constant expressionswitch case 语句错误:case 表达式必须是常量表达式
【发布时间】:2012-02-01 08:15:43
【问题描述】:

我的 switch-case 语句昨天运行良好。但是当我今天早上早些时候运行代码时,eclipse给了我一个错误,用红色强调了case语句并说:case表达式必须是常量表达式,它是常量我不知道发生了什么。下面是我的代码:

public void onClick(View src)
    {
        switch(src.getId()) {
        case R.id.playbtn:
            checkwificonnection();
            break;

        case R.id.stopbtn:
            Log.d(TAG, "onClick: stopping srvice");
            Playbutton.setImageResource(R.drawable.playbtn1);
            Playbutton.setVisibility(0); //visible
            Stopbutton.setVisibility(4); //invisible
            stopService(new Intent(RakistaRadio.this,myservice.class));
            clearstatusbar();
            timer.cancel();
            Title.setText(" ");
            Artist.setText(" ");
            break;

        case R.id.btnmenu:
            openOptionsMenu();
            break;
        }
    }

所有 R.id.int 都用红色下划线。

【问题讨论】:

  • 能否提供R.id.playbtn等的定义?一切都是静态的和最终的吗?
  • 可能你删除/修改了你的布局,而那些 id 不再存在或类似的东西......
  • R 类通常由 IDE/dev 工具生成,因此对于使用的 Android 版本通常是正确的。
  • 我的 R.id.* 都很好,并且存在于 android 的 gen 类中。它也在主布局中。

标签: java android switch-statement


【解决方案1】:

在常规的 Android 项目中,资源 R 类中的常量声明如下:

public static final int main=0x7f030004;

但是,从 ADT 14 开始,在库项目中,它们将被声明为:

public static int main=0x7f030004;

换句话说,常量在库项目中不是最终的。 因此您的代码将不再编译。

解决方案很简单:将 switch 语句转换为 if-else 语句。

public void onClick(View src)
{
    int id = src.getId();
    if (id == R.id.playbtn){
        checkwificonnection();
    } else if (id == R.id.stopbtn){
        Log.d(TAG, "onClick: stopping srvice");
        Playbutton.setImageResource(R.drawable.playbtn1);
        Playbutton.setVisibility(0); //visible
        Stopbutton.setVisibility(4); //invisible
        stopService(new Intent(RakistaRadio.this,myservice.class));
        clearstatusbar();
        timer.cancel();
        Title.setText(" ");
        Artist.setText(" ");
    } else if (id == R.id.btnmenu){
        openOptionsMenu();
    }
}

http://tools.android.com/tips/non-constant-fields

您可以使用以下命令将switch 语句快速转换为if-else 语句:

在 Eclipse 中
将光标移动到 switch 关键字并按 Ctrl + 1 然后选择

将“switch”转换为“if-else”。

在 Android Studio 中
将光标移动到 switch 关键字并按 Alt + Enter 然后选择

将“开关”替换为“如果”。

【讨论】:

  • 我将 switch-case 语句更改为 else-if 语句。这让我想知道我创建了一个新的 android 项目并使用了 switch-case 语句并且工作正常......
  • 可能是您的第一个项目正在使用库项目,而您的新项目没有。
  • 我不明白,对不起,我真的是这里的初学者..你能解释一下
  • 至少eclipse会让你自动转换为if/else。点击切换关键字。然后按 ctrl-1
  • 编译器需要在编译时知道表达式。如果没有 final 关键字,可以在运行时更改变量。
【解决方案2】:

取消选中项目属性中的“是库”对我有用。

【讨论】:

  • 右键单击您的项目名称。然后点击属性-> Android。弹出窗口的右下方是标有“库”的部分。在它下面,如果“is Library”选项被选中,如果你不希望你的项目成为一个库项目,就取消选中它。然后清理并重建。如果您希望它成为一个库项目,那么您必须将您的开关更改为 if else 条件,如其他地方所述。
  • 图书馆项目被标记为“是图书馆”是有原因的。这不是问题的正确解决方案 - 它会破坏您的 Android 项目结构,使应该是库的行为像常规应用程序一样。
【解决方案3】:

可以这样解决:

  1. 只需分配 整数
  2. variable 设为 final

示例:

public static final int cameraRequestCode = 999;

希望这会对你有所帮助。

【讨论】:

    【解决方案4】:

    R.id.*,因为 ADT 14 不再被声明为 final static int,所以你不能在 switch case 构造中使用。你可以改用 if else 子句。

    【讨论】:

    • 是的,我在 tools.android.com 上读过,我也尝试创建一个新项目并使用上面的代码,它工作得很好.. 怎么样?
    • tools.android.com/recent/buildchangesinrevision14 参见“图书馆项目改造”部分
    • 他们为什么做出这个改变是没有意义的。
    【解决方案5】:

    这个问题的简单解决方案是:

    点击switch,然后按CTL+1,它将把你的switch改为if-else块语句,解决你的问题

    【讨论】:

      【解决方案6】:

      如何使用其他解决方案来保留 nice 开关而不是 if-else:

      private enum LayoutElement {
          NONE(-1),
          PLAY_BUTTON(R.id.playbtn),
          STOP_BUTTON(R.id.stopbtn),
          MENU_BUTTON(R.id.btnmenu);
      
          private static class _ {
              static SparseArray<LayoutElement> elements = new SparseArray<LayoutElement>();
          }
      
          LayoutElement(int id) {
              _.elements.put(id, this);
          }
      
          public static LayoutElement from(View view) {
              return _.elements.get(view.getId(), NONE);
          }
      
      }
      

      所以在你的代码中你可以这样做:

      public void onClick(View src) {
          switch(LayoutElement.from(src)) {
          case PLAY_BUTTTON:
              checkwificonnection();
              break;
      
          case STOP_BUTTON:
              Log.d(TAG, "onClick: stopping srvice");
              Playbutton.setImageResource(R.drawable.playbtn1);
              Playbutton.setVisibility(0); //visible
              Stopbutton.setVisibility(4); //invisible
              stopService(new Intent(RakistaRadio.this,myservice.class));
              clearstatusbar();
              timer.cancel();
              Title.setText(" ");
              Artist.setText(" ");
              break;
      
          case MENU_BUTTON:
              openOptionsMenu();
              break;
          }
      }
      

      枚举是静态的,因此影响非常有限。唯一需要关注的窗口是涉及的双重查找(首先在内部 SparseArray 上,然后在开关表上)

      也就是说,这个枚举也可以用来以流畅的方式获取项目,如果需要,通过保留对 id 的引用......但这是其他时候的故事了。

      【讨论】:

      • 枚举在 Android 中是不鼓励的,因为它们的内存膨胀;这就是它们从未在 AOSP 中使用的主要原因 - 也是您到处都能看到整数的原因。
      【解决方案7】:

      当我在一个函数中使用 switch 并在我的类中声明了变量时,它抛出了这个错误:

      private void ShowCalendar(final Activity context, Point p, int type) 
      {
          switch (type) {
              case type_cat:
                  break;
      
              case type_region:
                  break;
      
              case type_city:
                  break;
      
              default:
                  //sth
                  break;
          }
      }
      

      当我在类的开头向变量声明final时,问题就解决了:

      final int type_cat=1, type_region=2, type_city=3;
      

      【讨论】:

      • enum 在这种情况下是 int 的更好替代品。方法的调用者将无法调用无效类型的函数。
      • 我有特定的 int 类型,所以如果我使用 int 就可以了。但是我想知道一个枚举示例:D
      • i have specific int types so its ok if i use ints 真的没有意义。关于枚举示例:docs.oracle.com/javase/tutorial/java/javaOO/enum.html
      • 我的意思是函数中传入的 int 变量类型将始终是这 3 种类型之一,因此它不会破坏任何东西,感谢枚举示例 :)
      • i mean that the incoming int variable type in the function will always be one of these 3 types so it won't break anything 这是你的假设。其他人可以使用任意数字错误地调用该函数。使用enum,您无需假设,它是由语言强制执行的。
      【解决方案8】:

      我想提一下,当我尝试将库添加到我的项目中时,我遇到了同样的情况。突然间所有的 switch 语句都开始显示错误!

      现在我试图删除我添加的库,即使那样它也不起作用。 “当我清理项目时”怎么会出现所有错误!

      【讨论】:

        【解决方案9】:

        只需将变量声明为 final

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-12
          • 2011-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多