Вопрос-ответ

Why can't I use switch statement on a String?

Почему я не могу использовать оператор switch для строки?

Будет ли эта функциональность внедрена в более позднюю версию Java?

Кто-нибудь может объяснить, почему я не могу этого сделать, например, технический способ работы оператора Java switch?

Переведено автоматически
Ответ 1

Операторы Switch с String обращениями были реализованы в Java SE 7, по крайней мере, через 16 лет после их первого запроса. Четкая причина задержки не была указана, но, вероятно, это было связано с производительностью.

Реализация в JDK 7

Теперь эта функция реализована в javac процессе "удаления сахара"; чистый высокоуровневый синтаксис, использующий String константы в case объявлениях, расширяется во время компиляции до более сложного кода, следующего шаблону. Результирующий код использует инструкции JVM, которые существовали всегда.

A switch с String падежами преобразуется в два переключателя во время компиляции. Первый отображает каждую строку в уникальное целое число — ее позицию в исходном переключателе. Это делается путем первого включения хэш-кода метки. Соответствующий случай - это if оператор, который проверяет равенство строк; если в хэше есть коллизии, тест является каскадным if-else-if. Второй переключатель отражает этот параметр в исходном коде, но заменяет метки регистра соответствующими позициями. Этот двухэтапный процесс упрощает сохранение управления потоком исходного переключателя.

Переключатели в JVM

Для получения более подробной технической информации о switch, вы можете обратиться к спецификации JVM, где описана компиляция операторов switch. В двух словах, есть две разные инструкции JVM, которые можно использовать для переключения, в зависимости от разреженности констант, используемых в cases. Эффективное выполнение обоих зависит от использования целочисленных констант в каждом конкретном случае.

Если константы плотные, они используются в качестве индекса (после вычитания наименьшего значения) в таблице указателей инструкций —the 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;
}
Ответ 2

Если у вас в коде есть место, где вы можете включить строку, то, возможно, лучше реорганизовать строку, чтобы она была перечислением возможных значений, которые вы можете включить. Конечно, вы ограничиваете потенциальные значения строк, которые у вас могут быть, значениями в перечислении, которые могут быть желательными, а могут и не быть.

Конечно, в вашем перечислении могла бы быть запись для 'other' и метод fromString (строка), тогда вы могли бы иметь

ValueEnum enumval = ValueEnum.fromString(myString);
switch (enumval) {
case MILK: lap(); break;
case WATER: sip(); break;
case BEER: quaff(); break;
case OTHER:
default: dance(); break;
}
Ответ 3

Ниже приведен полный пример, основанный на сообщении JeeBee, с использованием java enum вместо использования пользовательского метода.

Обратите внимание, что в Java SE 7 и более поздних версиях вы можете использовать объект String в выражении оператора switch вместо этого.

public class Main {

/**
* @param args the command line arguments
*/

public static void main(String[] args) {

String current = args[0];
Days currentDay = Days.valueOf(current.toUpperCase());

switch (currentDay) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
System.out.println("boring");
break;
case THURSDAY:
System.out.println("getting better");
case FRIDAY:
case SATURDAY:
case SUNDAY:
System.out.println("much better");
break;

}
}

public enum Days {

MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
}
Ответ 4

Переключатели, основанные на целых числах, могут быть оптимизированы для получения очень эффективного кода. Переключатели, основанные на другом типе данных, могут быть скомпилированы только в серию операторов if ().

По этой причине C & C ++ разрешают переключать только целочисленные типы, поскольку с другими типами это было бессмысленно.

Разработчики C # решили, что стиль важен, даже если в нем нет никаких преимуществ.

Разработчики Java, очевидно, думали так же, как разработчики C.

java string