This article covers the implementation details of String switch
introduced in Java 7. It is a syntactic sugar on top of the normal switch
operator.
Suppose you have the following method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public int switchTest( final String s ) { switch ( s ) { case "a" : System.out.println("aa"); return 11; case "b" : System.out.println("bb"); return 22; default : System.out.println("cc"); return 33; } }public int switchTest( final String s ) { switch ( s ) { case "a" : System.out.println("aa"); return 11; case "b" : System.out.println("bb"); return 22; default : System.out.println("cc"); return 33; } }
It is converted by javac
into the following code (decompiled back into Java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public int switchTest(String var1) { byte var3 = -1; switch(var1.hashCode()) { case 97: if(var1.equals("a")) { var3 = 0; } break; case 98: if(var1.equals("b")) { var3 = 1; } } switch(var3) { case 0: System.out.println("aa"); return 11; case 1: System.out.println("bb"); return 22; default: System.out.println("cc"); return 33; } }public int switchTest(String var1) { byte var3 = -1; switch(var1.hashCode()) { case 97: if(var1.equals("a")) { var3 = 0; } break; case 98: if(var1.equals("b")) { var3 = 1; } } switch(var3) { case 0: System.out.println("aa"); return 11; case 1: System.out.println("bb"); return 22; default: System.out.println("cc"); return 33; } }
The generated code consists of 2 parts:
-
Translation from
String
into a distinctint
for each case, which is implemented in the firstswitch
statement. -
The actual
switch
based onint
-s.
The first switch
contains a case
for each distinct String.hashCode
in the original String switch
labels. After matching by hash code, a string is compared for equality to every string with the same hash code. It is pretty unlikely that 2 strings used in switch
labels will have the same hash code, so in most cases you will end up with exactly one String.equals
call.
After seeing the generated code, it becomes clear why you can not use null
as a switch label: the first switch
starts from calculating the hashCode
of the switch
argument.
What can we say about the performance of the underlying int switch
? As you can find in one of my earlier articles, a switch
is implemented as a fixed map with a table size of approximately 20 (which is fine for most of common cases).
Finally, we should note that String.hashCode
implementation has implicitly became the part of the Java Language Specification after it was used in the
String switch
implementation. It can no longer be changed without breaking the .class
files containing String switch
, which were compiled with the older versions of Java.
The post String switch implementation appeared first on Java Performance Tuning Guide.