3

The rules of case usage say:

  1. The case expression must evaluate to a Compile Time Constant.

  2. case(t) expression must have same type as that of switch(t), where t is the type (String).

If i run this code :

public static void main(String[] args) {
    final String s=new String("abc");
    switch(s)
    {
       case (s):System.out.println("hi");
    }

}

It gives Compile-error as: "case expression must be a constant expression" On the other hand if i try it with final String s="abc";, it works fine.

As per my knowledge,String s=new String("abc") is a reference to a String object located on heap. And s itself is a compile-time constant.

Does it mean that final String s=new String("abc");isn't compile time constant?

Aman Arora
  • 1,232
  • 1
  • 10
  • 26

6 Answers6

2

In Java SE 7 and later, you can use a String object in the switch statement's expression.

You can only use constant expressions in the cases and no variables.

creating a String with a constructor isn't considered a constant.

Philipp Sander
  • 10,139
  • 6
  • 45
  • 78
2

Use this,

    String s= new String("abc");
    final String lm = "abc";

    switch(s)
    {
       case lm:
           case "abc": //This is more precise as per the comments
           System.out.println("hi");
           break;
    }

As per the documentation

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

The problem is your code final String s= new String("abc"); does not initializes a constant variable.

Deepak Bhatia
  • 6,230
  • 2
  • 24
  • 58
1

It doesn't consider new String() to be a constant (even though String is immutable).

Try this:

public static void main(String[] args)
{
    final String s = "abc";
    switch (s)
    {
        case (s):
            System.out.println("hi");
    }
}

Edit: I guess your switch (s) is a typo, there wouldn't be much point in that.

Also, if you're using constants in your switch statements like that, it's probably going to be clearer to extract them as a constant field, e.g. private static final String s = "abc";. And even clearer if you were to use an enum instead of strings, but I realise that isn't always possible.

stripybadger
  • 4,539
  • 3
  • 19
  • 26
  • `s` is a constant. Isn't it ? – Aman Arora Dec 20 '13 at 12:40
  • Not really. It's just a field or variable. The fact that you've made it final and have an immutable object doesn't make it a constant. You could use reflection to alter the byte array that backs a string for example. This would change the value of the string, thus violating the requirement for case statements to use constants. – stripybadger Dec 20 '13 at 12:44
  • Even if you change the value inside `String`, you can't change the value inside reference `s`.That means you can't make `s` point to something else now. Which makes it a constant. And as you can see i'm using `s` inside my catch and not `new String()`. – Aman Arora Dec 20 '13 at 12:49
  • No, s is just a reference to your string object. Which references the byte array within it. So if you altered the value in the byte array, it would cause `s` to change. `final String s` just means that you can't point s to a new object. It doesn't mean that `s` is a copy of the object as it was at that time. – stripybadger Dec 20 '13 at 12:52
  • In reference you don't have a byte array. Byte array stays on Heap ,but you reference stays on stack. Reference just points to your byte array. :) – Aman Arora Dec 20 '13 at 12:55
0

The thing is you can change the value of variable S anywhere in the switch so this probably can execute all the cases. So it gives "case expression must be a constant expression" error and in case if variable is final then its value cant be changed.

EDIT

In case you need to have Compile time constants and final variables are considered to be Runtime constants. As final variables can be delayed initialized and the compiler cannot determine.

eatSleepCode
  • 4,427
  • 7
  • 44
  • 93
0

The problem is that your trying to switch and test the case variable s. Which, is throwing the error. "case expression must be a constant expression". This has nothing to do with s per se... but using s as the case variable. Understand?

Here's a sample using the same variable that works properly.

private void switchTest() {
    final String s = new String("abc");
    switch (s) {
        case "abc":
            System.out.println("This works fine... woohoo.");
            break;
        default:
            System.out.println("Do something default.");
    }

}
Edward J Beckett
  • 5,061
  • 1
  • 41
  • 41
-1

what about an int or other primitive datatype as compile time constant for switch statement?

public class MainClass{ 
    public static void main(String[] argv){ 
        final int a = 1;
        final int b; 
        b = 2; 
        int x = 0; 
        switch (x) { 
            case a: // ok 
            case b: // compiler error 
        } 
    } 
}
GameDroids
  • 5,584
  • 6
  • 40
  • 59
  • public class MainClass{ public static void main(String[] argv){ final int a = 1; final int b; b = 2; int x = 0; switch (x) { case a: // ok case b: // compiler error } } } – Partha Sarathi Oct 20 '16 at 21:08
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you [earn](http://meta.stackoverflow.com/q/146472/169503) sufficient [reputation](http://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](http://stackoverflow.com/help/privileges/comment). If you have a related but different question, [ask a new question](http://stackoverflow.com/questions/ask) referencing this one if it will help provide context. – Bhargav Rao Oct 20 '16 at 21:09