Java – Non-static variable in case expression


I would like to access a public integer from another class for use in a switch statement as below:

StateManager sm = new StateManager(0);

switch (localState) {
    case (sm.ALL_COMPANIES_REQUEST): {
       //do something 
       //do this instead    

However, these variables need to be accessed by multiple threads, so I don't want to make them static. Unfortunately I am getting an error saying that case expressions must be constant. There are no methods that change these variables, they are constant, but it seems that without labeling them static the computer cannot figure that out. Anyone know how to get around this?

How about nesting the classes, this is an option as StateManager is really only useful to the class with the switch statement above. Would this be sufficient to use final alone?

Best Solution

The requirement is that the values on a switch statement are constant expressions or enum values; see JLS 14.11.

A constant expression is described in JLS 15.28. Essentially it is a compile time constant expression. So that means that something like this would not compile:

    static final int foo = someString.length();
    switch (x) {
        case foo: ...  // case label is not a >>compile time<< constant

However, your concern about static constants and threads is unfounded. The specification of final fields specifically states that they can be safely read without synchronization; see JLS 17.5.

(Besides, you wouldn't get deadlocks even if the fields weren't final. What you would get would be threads possibly seeing stale values of the field if they didn't synchronize properly on the parent object or class.)

So the answer to your question is:

  • if the constant is a compile time constant, you can just declare is as static final and the switch statement will compile, but
  • if the constant is NOT a compile time constant, then declaring it as static final won't help.

How about nesting the classes?

That won't make any difference.