Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why final variables cannot be used in switch statements?

When I type the following code into Eclipse, it complains that "case expressions must be constant expressions". If the array is marked final, its contents must be constant. Why is this invalid?

final String[] match={"a","b","c"};
switch (switchVar) {
case match[0]: /* Eclipse complains here about nonconstant switch */
    System.out.println("Matches");
    break;
default:
    System.out.println("No Match");
    break;
}
like image 972
rlee827 Avatar asked Feb 05 '23 19:02

rlee827


2 Answers

There's nothing constant about an array. Its contents may be mutated at any time. The reference will say the same, but match[0] could be something different at any point in time.

You have to use a constant value; one that's guaranteed not to change. Things like enums, primitive literals (and their boxed counterparts), and String literals are guaranteed not to change through this process, and are valid for use.

This does mean, however, that you can use a variable which is marked final and isn't mutable, though. Since array types are mutable, it doesn't work out as well - even if you reassign it to a final variable. You have to declare the literal.

Here's a simple snippet below, revising your existing code:

String switchVar = "a";
final String matchZero = "a";
switch (switchVar) {
    case matchZero: // valid since there's no way matchZero can ever be mutated
        System.out.println("Matches");
        break;
    default:
        System.out.println("No Match");
        break;
}
like image 91
Makoto Avatar answered Feb 15 '23 23:02

Makoto


If the array is marked final, its contents must be constant.

This is an incorrect understanding. A final variable only prevents new instances of the array being created, but it does not prevent the contents of the array being altered. I can do this with your existing code and it will be valid:

    final String[] match = {"a", "b", "c"};        
    match[0] = "b"; // CHANGE HERE
    switch (switchVar) {
        case "a": //Fixing this to make it compile
            /* Eclipse complains here about nonconstant switch */
            System.out.println("Matches");
            break;
        default:
            System.out.println("No Match");
            break;
    }

To make the code compile and to use the switch statement, you need to be using constants. So either declare constants or an in place string would make it work.

    final String[] match = {"a", "b", "c"};        
    switch (switchVar) {
        case "a": // CHANGE HERE
            /* Eclipse complains here about nonconstant switch */
            System.out.println("Matches");
            break;
        default:
            System.out.println("No Match");
            break;
    }

The reason why this is is simply because the The Java Language Specification on switch statements makes the assumption that all switch statements works on constant expressions.

like image 33
Shiraaz.M Avatar answered Feb 15 '23 23:02

Shiraaz.M