switch case语句错误:case表达式必须是常量表达式

Hea*_*gel 124 java android switch-statement

我的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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

Ben*_*oli 270

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

public static final int main=0x7f030004;
Run Code Online (Sandbox Code Playgroud)

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

public static int main=0x7f030004;
Run Code Online (Sandbox Code Playgroud)

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

解决方案很简单:将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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

将'switch'转换为'if-else'.

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

将'switch'替换为'if'.

  • 至少eclipse会让你自动将开关转换为if/else.单击switch关键字.然后点击ctrl-1 (7认同)
  • 编译器需要在编译时知道表达式。如果没有 `final` 关键字,则可以在运行时更改变量。 (2认同)

小智 52

取消选中项目中的"Is Library"属性对我有用.

  • 库项目标有"Is Library"的原因有多种.这不是解决问题的正确方法 - 它会破坏您的Android项目结构,使应该像常规应用程序一样的库. (5认同)
  • 右键单击您的项目名称.然后单击属性 - > Android.在弹出窗口的右下角是一个标有"图书馆"的部分.在其下,如果选中"is Library"选项,如果您不希望项目成为库项目,请取消选中它.然后清理并重建.如果您希望它是一个库项目,那么您必须将切换更改为if else条件,如其他地方所述. (2认同)

Til*_*ill 17

2023 年以上注意事项:

使用 Android Gradle Plugin 8.0.0,所有 R 类资源默认不再声明为最终/常量(因此在 switch 语句中不起作用)。如果您在 Android Studio 中使用 AGP 升级向导,它实际上会将此行添加到您的 gradle.properties 以保留旧行为:

android.nonFinalResIds=false
Run Code Online (Sandbox Code Playgroud)

但如果您不使用向导或开始新项目,这可能会让人感到惊讶。手动添加上面的行或使用 if/else 语句代替。


Hir*_*tel 12

解决方案可以这样做:

  1. 分配整型
  2. 变量最后

例:

public static final int cameraRequestCode = 999;
Run Code Online (Sandbox Code Playgroud)

希望这会帮助你.


Bla*_*elt 8

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

  • 为什么他们做出这种改变是没有意义的. (6认同)

Pir*_*hah 8

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

单击开关然后按CTL + 1,它会将您的开关更改为if-else阻止语句,并将解决您的问题


pab*_*sco 7

这个其他解决方案如何保持漂亮的开关而不是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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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