switch case statement error: case expressions must be constant expression
Asked Answered
W

10

150

My switch-case statement works perfectly fine yesterday. But when I run the code earlier this morning eclipse gave me an error underlining the case statements in color red and says: case expressions must be constant expression, it is constant I don't know what happened. Here's my code below:

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

All R.id.int are all underlined in red.

Worldbeater answered 1/2, 2012 at 8:15 Comment(4)
Can you provide the definition of R.id.playbtn etc.? Is everything static and final?Strophe
Probably you deleted/modified your layout and those ids don't exist anymore or something like that...Sorilda
The class R is typically generated by the IDE/dev tools, so it's usually correct for the version of Android in use.Woodham
my R.id.* are all fine and exist in the gen class of android.. and its also in the main layout.Worldbeater
B
308

In a regular Android project, constants in the resource R class are declared like this:

public static final int main=0x7f030004;

However, as of ADT 14, in a library project, they will be declared like this:

public static int main=0x7f030004;

In other words, the constants are not final in a library project. Therefore your code would no longer compile.

The solution for this is simple: Convert the switch statement into an if-else statement.

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

You can quickly convert a switch statement to an if-else statement using the following:

In Eclipse
Move your cursor to the switch keyword and press Ctrl + 1 then select

Convert 'switch' to 'if-else'.

In Android Studio
Move your cursor to the switch keyword and press Alt + Enter then select

Replace 'switch' with 'if'.

Ballast answered 1/2, 2012 at 9:39 Comment(9)
i change my switch-case statement to else-if statement.. It just got me wondering i create a new android project and used a switch-case statement and work fine..Worldbeater
It could be that your first project is using a library project and your new project isn't.Ballast
i dont understand that sorry im really a beginner here.. can you explainWorldbeater
Your answer was exactly what I needed. I just converted an app project to a library project and was getting a few of these errors, and had not noticed that the final keyword had been dropped from the constant declarations. After reading your answer, saw right away that the old declaration for my constant btnSave was: public static final int btnSave=0x7f0a001f; while the one for the library was: public static int btnSave=0x7f0a001f;Psid
So, why switch specifically doesn't allow that?Serum
The compiler needs the expression to be known at compile time. Without the final keyword, a variable can be changed at runtime.Ballast
Note that final is not sufficient. If the value of the final variable is created through a method, it will sadly not work either.Wersh
Special thanks for the shortcuts to auto convert switch/case to if/else!Pergrim
Note that as of Android Gradle Plugin 8.0.0, ALL project R.class resources are non-final by defaultBerky
C
52

Unchecking "Is Library" in the project Properties worked for me.

Chilblain answered 6/11, 2013 at 12:15 Comment(2)
Right click on your project name. Then click on properties -> Android. On the lower right of the popup is a section labled "Library". Under it, if the "is Library" option is checked, uncheck it if you don't want your project to be a library project. Then clean and rebuild. If you want it to be a library project, then you have to change your switch to an if else conditional as stated elsewhere.Trefler
There are reasons why a library project is marked with "Is Library". This is not a proper solution to the problem - it will break your Android project structure by making what should be libraries to behave like regular apps.Cowshed
B
19

Note for 2023+:

With Android Gradle Plugin 8.0.0 all your R-class resources are by default no longer declared as final/constant (hence won't work in switch statements). If you use the AGP upgrade wizard in Android Studio, it will actually add this line to your gradle.properties to keep the old behavior:

android.nonFinalResIds=false

But if you don't use the wizard or start with a new project, this might come as a surprise. Add above's line manually or use if/else statements instead.

Berky answered 27/7, 2023 at 17:20 Comment(0)
D
13

Solution can be done be this way:

  1. Just assign the value to Integer
  2. Make variable to final

Example:

public static final int cameraRequestCode = 999;

Hope this will help you.

Doc answered 1/2, 2016 at 9:44 Comment(0)
K
11

Simple solution for this problem is :

Click on the switch and then press CTL+1, It will change your switch to if-else block statement, and will resolve your problem

Kierstenkieselguhr answered 23/3, 2014 at 8:14 Comment(0)
S
9

R.id.*, since ADT 14 are not more declared as final static int so you can not use in switch case construct. You could use if else clause instead.

Slavocracy answered 1/2, 2012 at 8:20 Comment(3)
yes i have read that on tools.android.com, i also tried to create a new project and used the code above and it works just fine.. how is that?Worldbeater
tools.android.com/recent/buildchangesinrevision14 see the "Library Project Revamp" sectionSlavocracy
Why did they make this change is makes no sense.Lamond
T
7

How about this other solution to keep the nice switch instead of an 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);
    }

}

So in your code you can do this:

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

Enums are static so this will have very limited impact. The only window for concern would be the double lookup involved (first on the internal SparseArray and later on the switch table)

That said, this enum can also be utilised to fetch the items in a fluent manner, if needed by keeping a reference to the id... but that's a story for some other time.

Thirsty answered 11/3, 2014 at 11:21 Comment(2)
Enums are discouraged in Android due to their memory bloat; and that is the major reason why they are never used in AOSP - and the reason why you see ints everywhere.Cowshed
#5143756Thirsty
L
3

It was throwing me this error when I using switch in a function with variables declared in my class:

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

The problem was solved when I declared final to the variables in the start of the class:

final int type_cat=1, type_region=2, type_city=3;
Luscious answered 10/9, 2013 at 13:37 Comment(6)
enum is a better alternative to int in this case. The caller of the method won't be able to call the function with invalid type.Landre
i have specific int types so its ok if i use ints. However i would like to know an example with enum :DLuscious
i have specific int types so its ok if i use ints Doesn't really make sense. Regarding enum example: docs.oracle.com/javase/tutorial/java/javaOO/enum.htmlLandre
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 thanks for the enum example :)Luscious
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 This is your assumption. Someone else can call the function incorrectly with arbitrary number. With enum, you don't need to assume, it is enforced by the language.Landre
hmm ok your argument is true if someone else doesn't know how to call the function or pass wrong int input but someone could put in the default branch return false if he changes the return of the function also to Boolean. anyway i suppose its a better way to call a function with enum variables preset by the user.Luscious
O
2

I would like to mention that, I came across the same situation when I tried adding a library into my project. All of a sudden all switch statements started to show errors!

Now I tried to remove the library which I added, even then it did not work. how ever "when I cleaned the project" all the errors just went off !

Ovular answered 18/6, 2013 at 18:36 Comment(0)
I
0

Simply declare your variable to final

Inoculum answered 22/10, 2020 at 5:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.