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