Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is switch with strings more than just syntactic sugar? [duplicate]

Since Java 1.7, strings can be used with switch statements, which has me wondering about something. switch statements on integer values be turned into jump tables, which are faster than simply doing if checks on integers calculated at runtime; can a similar optimization be done with strings or is this just syntactic sugar?

like image 338
Paul Manta Avatar asked Apr 18 '15 19:04

Paul Manta


2 Answers

The compiler optimizes a switch statement based on string values using the hashCode() method, and then uses a lookup table in the bytecode. This is generally more efficient than an if-else statement.

For example, the following:

String string = "x";
switch(string) {
    case "x": System.out.println("x");
              break;
    case "y": System.out.println("y");
              break;
    case "z": System.out.println("z");
              break;
}

is transformed to this bytecode:

ldc "x"
astore_1
aload_1
astore_2
iconst_m1
istore_3
aload_2
invokevirtual java/lang/String/hashCode()I
tableswitch 120
  10
  17
  24
  default: 30
aload_2
ldc "x"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_0
istore_3
goto 30
aload_2
ldc "y"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_1
istore_3
goto 30
aload_2
ldc "z"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_2
istore_3
iload_3
tableswitch 0
  32
  36
  40
  default: 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "x"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "y"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "z"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
like image 93
M A Avatar answered Oct 04 '22 01:10

M A


Yes switch with string is a syntatic sugar. From here

1) Strings in Switch are syntactic sugar, no change in JVM level.

2) Internally it uses equals method to compare, which means, if you pass null it will throw java.lang.NullPointerException, so beware of that.

3) Strings in switch statements are case sensitive, prefer to use only one case and convert input to preferred case before passing them to switch statement.

Also check How String in Switch works in Java 7

From the same link if you see the example:

public class StringInSwitchCase{ 
    public static void main(String[] args) { 
        String mode = args[0]; switch (mode) { 
            case "ACTIVE": System.out.println("Application is running on Active mode"); 
                break; 
            case "PASSIVE": System.out.println("Application is running on Passive mode"); 
                break; 
           case "SAFE": System.out.println("Application is running on Safe mode"); 
        } } }

and the Decompiled Code :

import java.io.PrintStream; 
public class StringInSwitchCase{ 
    public StringInSwitchCase() { } 
    public static void main(string args[]) { 
        String mode = args[0]; String s; 
        switch ((s = mode).hashCode()) { 
            default: break; 
            case -74056953: if (s.equals("PASSIVE")) { 
                System.out.println("Application is running on Passive mode"); } 
                break; 
            case 2537357: if (s.equals("SAFE")) { System.out.println("Application is running on Safe mode"); }
                break; 
            case 1925346054: if (s.equals("ACTIVE")) { System.out.println("Application is running on Active mode"); } 
                break; } } }

you will find out that String in Switch works by using hashCode() and equals() method.

As expected it uses hashCode() method for switching and equals() method for verification, This means it's just a syntactic sugar, rather than an inbuilt native functionality.

like image 33
Rahul Tripathi Avatar answered Oct 04 '22 01:10

Rahul Tripathi