Я читал спецификацию JVM для компиляции ключей и интересовался тем, как скомпилирован оператор switch на String. Ниже приведен метод проверки (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;
}
}
Я ожидаю, что этот метод будет скомпилирован в простой lookupswitch на hashCode строки, но вдруг
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
Как вы могли видеть, в ветвях первого поискового переключателя JVM вместо этого делает реальные индексы генерации работы для последующих tableswitch (строка 84).
Tableswitch должен работать быстро, поэтому не приносит много дополнительной работы. Но в любом случае, какова цель создания дополнительного коммутатора?
Обновление
Я понимаю возможность конфликтов hashCode. То, что я пытаюсь сказать, заключается в том, что вместо последующего tablewitch компилятор мог перенести всю реальную работу с последующих таблиц на первый, а затем использовать ifeq, чтобы перейти к концу всех ветвей коммутатора. Таким образом, один из возможных ответов, которые я вижу здесь, заключается в том, что в первом компиляторе коммутатора пытается прекомпретировать метку для перехода ifeq на основе известного числа случаев, но я не уверен, что это единственная причина.
Update2
Как предложил @ericbn, я попытался скомпилировать
switch (i) {
case 97: return -100;
case 51713: return 1;
case 99: return 2;
default: return -1;
}
с я как int и компилятор дал мне простой lookupswitch.