Java 7 String switch декомпилирован: неожиданная инструкция
Я декомпилировал очень простой класс, который использует новую функцию Java String Switch.
Класс:
public class StringSwitch {
public static void main(String[] args) {
final String color = "red";
switch (color) {
case "red":
System.out.println("IS RED!");
break;
case "black":
System.out.println("IS BLACK");
break;
case "blue":
System.out.println("IS BLUE");
break;
case "green":
System.out.println("IS GREEN");
break;
}
}
}
Запуск Java 7 "javap" против этого класса генерирует интересный набор инструкций (полный разобранный код доступен здесь):
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
...
12: lookupswitch { // 4
112785: 56
3027034: 84
93818879: 70
98619139: 98
default: 109
}
56: aload_2
57: ldc #2 // String red
...
110: tableswitch { // 0 to 3
0: 140
1: 151
2: 162
3: 173
default: 181
}
140: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
143: ldc #9 // String IS RED!
...
181: return
"LOOKUPSWITCH" - это инструкция, используемая, когда случай коммутатора разрежен и может заменить TABLESWITCH, который является инструкцией по умолчанию для операторов "switch".
Итак, вопрос в том, почему мы видим "LOOKUPSWITCH", а затем "TABLESWITCH"?
Спасибо
Luciano
Ответы
Ответ 1
С помощью строк в коммутаторе поиск правильного оператора case - это двухэтапный процесс.
- Вычислить хэш-код строки коммутатора и искать "hashcode match" среди операторов case, это делается через LOOKUPSWITCH. Обратите внимание на большие целые числа в LOOKUPSWITCH, это хэш-коды строк в операторах case.
- Теперь 2 строки могут иметь один и тот же хэш-код, каким бы маловероятным это ни было. Следовательно, фактическое сравнение строк должно все же иметь место. Следовательно, как только хеш-код будет согласован, строка переключателя сравнивается со строкой в согласованном случае. Инструкции, сделанные между LOOKUPSWITCH и TABLESWITCH, делают именно это. После подтверждения соответствия код, который должен быть выполнен для согласованного оператора case, достигается через TABLESWITCH.
Также обратите внимание, что полезно указать, какой компилятор вы использовали - javac или ECJ (компилятор Eclipse для java). Оба компилятора могут генерировать байт-код по-разному.