为什么要将String编译切换为两个开关

我在编译开关时阅读了JVM规范 ,并对如何编译String上的switch语句感兴趣。 这是我检查的测试方法(JDK1.7.0_40):

static int test(String i) { switch (i) { case "a": return -100; case "45b": return 1; case "c": return 2; default: return -1; } } 

我希望这个方法可以在string的hashCode上编译成简单的lookupswitch,但突然之间

 static int test(java.lang.String); Code: 0: aload_0 1: astore_1 2: iconst_m1 3: istore_2 4: aload_1 5: invokevirtual #6 // Method java/lang/String.hashCode:()I 8: lookupswitch { // 3 97: 44 99: 72 51713: 58 default: 83 } 44: aload_1 45: ldc #7 // String a 47: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 50: ifeq 83 53: iconst_0 54: istore_2 55: goto 83 58: aload_1 59: ldc #9 // String 45b 61: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 64: ifeq 83 67: iconst_1 68: istore_2 69: goto 83 72: aload_1 73: ldc #10 // String c 75: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 78: ifeq 83 81: iconst_2 82: istore_2 83: iload_2 84: tableswitch { // 0 to 2 0: 112 1: 115 2: 117 default: 119 } 112: bipush -100 114: ireturn 115: iconst_1 116: ireturn 117: iconst_2 118: ireturn 119: iconst_m1 120: ireturn 

正如您所看到的,在第一个lookupswitch的分支中,JVM并没有为后续的tableswitch(第84行)做真正的工作生成索引。
Tableswitch应该快速工作,所以不会带来很多额外的工作。 但无论如何,产生额外开关的目的是什么?
更新
我理解hashCode冲突的可能性。 我想说的是,编译器可以将所有实际工作从后续的tableswitch移到first,然后使用ifeq跳转到所有switch分支的末尾,而不是后续的tableswitch。 所以我在这里看到一个可能的答案:在第一个开关编译器尝试根据已知的案例数量为ifeq跳转预先计算标签,但我不确定这是唯一的原因。

UPDATE2
正如@ericbn建议的那样,我试图编译

 switch (i) { case 97: return -100; case 51713: return 1; case 99: return 2; default: return -1; } 

用i作为int和编译器给了我简单的lookupswitch。

来自javac源代码的引用:

  * The general approach used is to translate a single * string switch statement into a series of two chained * switch statements: the first a synthesized statement * switching on the argument string's hash value and * computing a string's position in the list of original * case labels, if any, followed by a second switch on the * computed integer value. The second switch has the same * code structure as the original string switch statement * except that the string case labels are replaced with * positional integer constants starting at 0. * * The first switch statement can be thought of as an * inlined map from strings to their position in the case * label list. An alternate implementation would use an * actual Map for this purpose, as done for enum switches. * * With some additional effort, it would be possible to * use a single switch statement on the hash code of the * argument, but care would need to be taken to preserve * the proper control flow in the presence of hash * collisions and other complications, such as * fallthroughs. Switch statements with one or two * alternatives could also be specially translated into * if-then statements to omit the computation of the hash * code.