2

I had a Switch referencing Resource Ids from R.java in a Library Project:

switch (code) {

    case R.id.code_one:
        blah();
        break;
    case R.id.code_two:
        bleh();
        break;
}

From ADT 14, R fields are no longer final, so Google suggests to change the switch into nested if's. Fair enough.

However, I wonder why this doesn't work:

final int CODE_ONE=R.id.code_one, CODE_TWO=R.id.code_two;
switch (code) {

    case CODE_ONE:
        blah();
        break;
    case CODE_TWO:
        bleh();
        break;
}

or this:

class blih {
    private final static int CODE_ONE=R.id.code_one, CODE_TWO=R.id.code_two;
    void bluh(int code) {
        switch (code) {

            case CODE_ONE:
                blah();
                break;
            case CODE_TWO:
                bleh();
                break;
        }
    }
}

All them complain with the error "Case statements must be constant expressions" ... aren't they, specially the first one? Whichever the value R.id.xxx might be, aren't I "finalizing" it into a snapshot constant?

rupps
  • 9,712
  • 4
  • 55
  • 95

2 Answers2

3

Case statements must be constant expressions at compile time. If you initialize them at runtime, they are not constants.

final does not mean "compile-time constant". It only means "can be assigned only once". This does enable the compiler to inline values at compile-time if the final value is known, allowing initialized final ints to be used in case expressions.

laalto
  • 150,114
  • 66
  • 286
  • 303
3

It doesn't work because:

  • The case label in the switch statement must be a compile-time constant expression.
  • Your final variables CODE_ONE and CODE_TWO are not compile-time constant expressions because they are not initialized with compile-time constant expressions.

The requirement for case labels to be compile-time constant expressions:

Details from the language specification

From the Java language specification, section 14.11: The switch statement:

These labels are said to be associated with the switch statement, as are the values of the constant expressions (§15.28) or enum constants (§8.9.1) in the case labels.

and:

  • No two of the case constant expressions associated with a switch statement may have the same value.

From the Java language specification, section 15.28: **Constant Expressions**:

15.28. Constant Expressions ... A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

  • ... [other examples elided]
  • Simple names (§6.5.6.1) that refer to constant variables (§4.12.4).
  • Qualified names (§6.5.6.2) of the form TypeName . Identifier that refer to constant variables (§4.12.4).

The JLS on constant variables, in section 4.12.4: final Variables

4.12.4 final Variables ... A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • +1 for the thorough explanation, however I like @laalto 's answer better because it's simpler and resumes all the docs. Thanks for linking all the official docs ! – rupps Sep 09 '14 at 14:28
  • @rupps - Okay, I finished writing this more precise answer, for the benefit of those who come to your question in the future. Good point about simplicity; I separated the JLS extracts into a separate details section. – Andy Thomas Sep 09 '14 at 15:31