Операторы switch с Stringделами были реализованы в Java SE 7 , по крайней мере, через 16 лет после их первого запроса. Четкой причины задержки предоставлено не было, но, скорее всего, это было связано с производительностью.
Реализация в JDK 7
В настоящее время эта функция реализована в процессе javac «удаления сахара»; чистый высокоуровневый синтаксис с использованием Stringконстант в caseобъявлениях расширяется во время компиляции в более сложный код, следуя шаблону. Полученный код использует инструкции JVM, которые существовали всегда.
А switchс Stringделами во время компиляции переводится в два ключа. Первая отображает каждую строку в уникальное целое число - ее положение в исходном переключателе. Это делается путем первого включения хеш-кода метки. Соответствующий случай - это ifоператор, который проверяет равенство строк; если в хэше есть коллизии, тест является каскадным if-else-if. Второй переключатель отражает это в исходном исходном коде, но заменяет метки регистра соответствующими позициями. Этот двухэтапный процесс позволяет легко сохранить управление потоком исходного переключателя.
Переключатели в JVM
Для большей технической глубины switchвы можете обратиться к Спецификации JVM, где описана компиляция операторов switch . В двух словах, есть две разные инструкции JVM, которые можно использовать для коммутатора, в зависимости от разреженности констант, используемых в случаях. Оба зависят от использования целочисленных констант для эффективного выполнения каждого случая.
Если константы плотные, они используются в качестве индекса (после вычитания наименьшего значения) в таблицу указателей инструкций - tableswitchинструкцию.
Если константы редкие, выполняется бинарный поиск правильного регистра - lookupswitchинструкция.
В де-Обсахаривания switchна Stringобъектах, обе инструкции могут быть использованы. lookupswitchПодходят для первого переключателя на хэш - кодах , чтобы найти исходное положение корпуса. Полученный порядковый номер является естественным соответствием для tableswitch.
Обе инструкции требуют, чтобы целочисленные константы, назначенные каждому случаю, были отсортированы во время компиляции. Во время выполнения, хотя O(1)производительность tableswitchобычно выглядит лучше, чем O(log(n))производительность lookupswitch, требуется некоторый анализ, чтобы определить, является ли таблица достаточно плотной, чтобы оправдать компромисс между пространством и временем. Билл Веннерс (Bill Venners) написал отличную статью, которая более подробно описывает это, а также подробное описание других инструкций по управлению потоком Java.
До 7 JDK
До JDK 7 enumможно было бы приблизиться к Stringпереключателю на основе. При этом используется статическийvalueOf метод, сгенерированный компилятором для каждого enumтипа. Например:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}