То, что я использую
find . \( -name "*.h" -o -name "*.cpp" \) -print
Операторы переключения с String
случаи были реализованы в [1 124] Java SE 7, по крайней мере 16 лет после того, как их сначала требовали. А ясная причина задержки не была обеспечена, но это, вероятно, имело отношение к производительности.
опция была теперь реализована в javac
с процессом "de-sugaring"; чистый, высокоуровневый синтаксис с помощью String
константы в case
объявления расширен во время компиляции в более сложный код после шаблона. Получающийся код использует инструкции по JVM, которые всегда существовали.
А switch
с String
случаи переводится в два переключателя во время компиляции. Первые карты каждая строка к уникальному integer— его положение в исходном переключателе. Это сделано первым включением хэш-кода маркировки. Соответствующий случай if
оператор, который тестирует строковое равенство; если существуют коллизии на хеше, тест является расположением каскадом if-else-if
. Вторые зеркала переключателя, что в коде первоисточника, но заменах случай маркирует их соответствующими положениями. Этот двухступенчатый процесс облегчает сохранять управление потоком исходного переключателя.
Для большей технической глубины на switch
, можно обратиться к Спецификации JVM, где компиляция операторов переключения описана. Короче говоря существует две различных инструкции по JVM, которые могут использоваться для переключателя, в зависимости от разреженности констант, используемых случаями. Оба зависят от использования целочисленных констант для каждого случая для выполнения эффективно.
, Если константы являются плотными, они используются в качестве индекса (после того, как, вычитая самое низкое значение) в таблицу инструкции pointers— tableswitch
инструкция.
, Если константы редки, двоичный поиск корректного случая является performed— lookupswitch
инструкция.
В de-sugaring switch
на [1 113] объекты, обе инструкции, вероятно, будут использоваться. Эти lookupswitch
подходит для первого, включают хэш-коды для нахождения исходного положения случая. Получающийся ординал является естественным пригодным для tableswitch
.
Обе инструкции требуют, чтобы целочисленные константы, присвоенные каждому случаю, были отсортированы во время компиляции. Во времени выполнения, в то время как O(1)
производительность [1 117] обычно кажется лучше, чем O(log(n))
производительность [1 119], это требует, чтобы некоторый анализ определил, является ли таблица достаточно плотной для выравнивания по ширине space– компромисс времени. Bill Venners записал большая статья , которая касается этого более подробно, наряду со взглядом под капотом на другие инструкции по управлению потоком Java.
До JDK 7, enum
мог приблизиться String
- базирующийся переключатель. Это использует помехи valueOf
метод, сгенерированный компилятором на каждом enum
тип. Например:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}
James Curran кратко говорит: "Переключатели на основе целых чисел могут быть оптимизированы к очень efficent код. Переключатели на основе другого типа данных могут только быть скомпилированы в серию если () операторы. По этой причине C & C++ только позволяет, включает целые типы, так как это было бессмысленно с другими типами".
Мое мнение, и это только, что, то, что, как только Вы начинаете включать непримитивы, необходимо начать думать о, "равняется" по сравнению с "==". Во-первых сравнение двух строк может быть довольно длинной процедурой, добавив к проблемам производительности, которые упомянуты выше. Во-вторых, если там включит строки то будет спрос на включение строк, игнорирующих регистр, включая строки, рассматривая/игнорируя локаль, включая строки на основе regex.... Я одобрил бы решение, которое сэкономило много времени для разработчиков языка за счет небольшого количества времени для программистов.
Если у Вас есть место в Вашем коде, где можно включить Строку, то может быть лучше осуществить рефакторинг Строку, чтобы быть перечислением возможных значений, которые можно включить. Конечно, Вы ограничиваете потенциальные ценности Строк, которые Вы можете иметь тем в перечислении, которое может или не может быть желаемо.
, Конечно, Ваше перечисление могло иметь запись для 'другого' и 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;
}
Переключатели на основе целых чисел могут быть оптимизированы к очень efficent код. Переключатели на основе другого типа данных могут только быть скомпилированы в серию если () операторы.
По этой причине C & C++ только позволяет, включает целые типы, так как это было бессмысленно с другими типами.
разработчики C# решили, что стиль был важен, даже если не было никакого преимущества.
разработчики Java, по-видимому, думали как разработчики C.
Около вышеупомянутых хороших аргументов я добавлю, что партия людей сегодня видит switch
как устаревший остаток от процедурного прошлого Java (назад ко временам C).
я не полностью совместно использую это мнение, я думаю switch
, может иметь его полноценность в некоторых случаях, по крайней мере, из-за его скорости, и так или иначе это лучше, чем некоторый ряд расположения каскадом числового else if
, я видел в некотором коде...
, Но действительно, стоит посмотреть на случай, где Вы нуждаетесь в переключателе и видите, не может ли это быть заменено чем-то больше OO. Например, перечисления в Java 1.5 +, возможно, HashTable или некоторый другой набор (когда-то я сожалею, что у нас нет (анонимных) функций как у гражданина первого класса, как в Lua —, который не имеет переключателя — или JavaScript), или даже полиморфизм.