7

I wrote the following code in Java which runs fine :

public class test {
    public static void main(String[] args) {
        final String s1 = "s1" ;
        final String s2 = "s2" ;

        String s = "s1" ;
        switch(s) {
            case s1 : System.out.println("s1") ;
                break ;
            case s2 : System.out.println("s2") ;
                break ;
        }
    }
}

But when I write the following code :

public class test {
    public static void main(String[] args) {
        final String s1 = "s1".toString() ;
        final String s2 = "s2".toString() ;

        String s = "s1" ;
        switch(s) {
            case s1 : System.out.println("s1") ;
                break ;
            case s2 : System.out.println("s2") ;
                break ;
        }
    }
}

I get the following error :

test.java:8: error: constant string expression required
                    case s1 : System.out.println("s1") ;
                         ^
test.java:10: error: constant string expression required
                    case s2 : System.out.println("s2") ;

I am looking for an explanation for this as I could not understand why is the second code giving me this error.

user3282758
  • 1,379
  • 11
  • 29
  • 2
    http://stackoverflow.com/questions/3827393/java-switch-statement-constant-expression-required-but-it-is-constant [dupplicate] – Sanka Sep 05 '16 at 16:33
  • Also see my answer [here](http://stackoverflow.com/questions/39157370/java-code-wont-compile-due-to-attribute-must-be-a-constant-expression-error/39157786#39157786) – ajb Sep 05 '16 at 17:15

1 Answers1

11

Because "s1".toString() is not a compile-time constant expression. Only compile-time constants (or enum constant names) can be used as labels in a switch statement. See the Java Language Specification, Section 15.28 for the rules for what constitutes a constant expression. (And see JLS §14.11 for the rules for the switch statement.)

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • can you clarify why the compiler can't infer that an invocation of toString() in a string literal is not equivalent to a compile-time constant? – fsb Sep 05 '16 at 16:32
  • From the mentioned JLS section, in this case the constant expression falls under "Simple names (§6.5.6.1) that refer to constant variables (§4.12.4)" where the constant variable is the `final` variable. – M A Sep 05 '16 at 16:33
  • 1
    @fsb - It probably could, but that just isn't part of the rules according to the specification. – Ted Hopp Sep 05 '16 at 16:33
  • @AR.3 - How is that? `"s1".toString()` is not a constant expression according to the rules (there's no simple name there!) and according to §4.12.4, "a _constant variable_ is a `final` variable of primitive type or type `String` **that is initialized with a constant expression**" (emphasis added). Therefore `s1` is not a simple name that refers to a constant variable. – Ted Hopp Sep 05 '16 at 16:37
  • @TedHopp I was referring to the first case. My comment was to further pinpoint the relevant part of your quote :) – M A Sep 05 '16 at 16:55
  • 1
    @AR.3 - Ah. I thought you were objecting to my answer. OP didn't actually ask about the first case, only why the second case was failing, but it is good to point out why the first case works. Thanks. – Ted Hopp Sep 05 '16 at 16:58
  • 1
    @fsb Because, in general, method calls return values that aren't known at compile time. Because of that, method calls aren't allowed in constant expressions. The Java designers could have tried to find a way to allow a certain list of method calls as potentially returning constant values, but that would have added complexity to the language rules. – ajb Sep 05 '16 at 17:21