Эта функциональность будет добавлена в более позднюю версию Java?
Может кто-нибудь объяснить, почему я не могу сделать это, например, в техническом смысле, как switch
работает утверждение Java ?
java
string
switch-statement
Алекс Бердсли
источник
источник
"Don't hold your breath."
lol, bugs.sun.com/bugdatabase/view_bug.do?bug_id=1223179Ответы:
Операторы 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
для выполнения каких-либо действий на основе,str
я бы сказал, что если-еще предпочтительнее, так как он позволяет обрабатыватьstr
значения за пределами диапазона КРАСНЫЙ, СИНИЙ, без необходимости перехватывать исключениеvalueOf
или вручную проверять совпадение с именем каждый тип перечисления, который просто добавляет ненужные издержки. По моему опыту имеет смысл использоватьvalueOf
для преобразования в перечисление, только если позднее было необходимо типизированное представление значения String.(hash >> x) & ((1<<y)-1)
будет давать разные значения для каждой строки,hashCode
которая отличается и(1<<y)
меньше чем вдвое больше строк (или в по крайней мере, не намного больше, чем это).Если в вашем коде есть место, где вы можете включить строку, то может быть лучше реорганизовать строку, чтобы она представляла собой перечисление возможных значений, которые вы можете включить. Конечно, вы можете ограничить потенциальные значения строк, которые вы можете иметь, перечисленными в перечислении, что может быть или не быть желательным.
Конечно, в вашем перечислении может быть запись для «other» и метод fromString (String), тогда вы можете иметь
источник
Ниже приведен полный пример, основанный на публикации JeeBee, с использованием перечислений java вместо использования пользовательских методов.
Обратите внимание, что в Java SE 7 и более поздних версиях вы можете использовать объект String в выражении оператора switch.
источник
Переключатели на основе целых чисел могут быть оптимизированы для очень эффективного кода. Переключатели, основанные на другом типе данных, могут быть скомпилированы только в серию операторов if ().
По этой причине C & C ++ разрешает переключаться только на целочисленные типы, поскольку с другими типами это было бессмысленно.
Дизайнеры C # решили, что стиль важен, даже если не было никакого преимущества.
Дизайнеры Java, очевидно, думали как дизайнеры C.
источник
Пример прямого
String
использования начиная с версии 1.7 также может быть показан:источник
Джеймс Керран кратко говорит: «Переключатели, основанные на целых числах, могут быть оптимизированы до очень эффективного кода. Переключатели, основанные на другом типе данных, могут быть скомпилированы только в серию операторов if (). По этой причине C & C ++ разрешает переключать только целочисленные типы, так как это было бессмысленно с другими типами ".
Мое мнение, и только это, заключается в том, что как только вы начинаете переключаться на не примитивы, вы должны начать думать о «равных» против «==». Во-первых, сравнение двух строк может быть довольно длительной процедурой, добавляя к проблемам производительности, которые упомянуты выше. Во-вторых, если происходит переключение строк, будет требоваться включение строк без учета регистра, включение строк с учетом / игнорирование локали, переключение строк на основе регулярных выражений .... Я бы одобрил решение, которое сэкономило много времени для Языковые разработчики за счет небольшого количества времени для программистов.
источник
matched
иnot matched
. (Тем не менее, не принимая во внимание такие вещи, как [именованные] группы / и т.д.).Помимо приведенных выше хороших аргументов, я добавлю, что многие люди сегодня считают
switch
устаревшим остатком процедурного прошлого Java (назад в C раз).Я не полностью разделяю это мнение, я думаю,
switch
что в некоторых случаях он может быть полезен, по крайней мере, из-за его скорости, и в любом случае он лучше, чем некоторые серии каскадных чисел, которыеelse if
я видел в некотором коде ...Но действительно, стоит взглянуть на случай, когда вам нужен переключатель, и посмотреть, не может ли он быть заменен чем-то более оригинальным. Например, перечисления в Java 1.5+, возможно, HashTable или какая-то другая коллекция (иногда я сожалею, что у нас нет (анонимных) функций в качестве первоклассного гражданина, как в Lua - у которого нет переключателя - или JavaScript) или даже полиморфизма.
источник
Если вы не используете JDK7 или выше, вы можете использовать его
hashCode()
для имитации. ПосколькуString.hashCode()
обычно возвращает разные значения для разных строк и всегда возвращает одинаковые значения для одинаковых строк, это довольно надежно (разные строки могут создавать тот же хеш-код, что и @Lii, упомянутый в комментарии, например,"FB"
и"Ea"
). См. Документацию .Итак, код будет выглядеть так:
Таким образом, вы технически включаете
int
.В качестве альтернативы вы можете использовать следующий код:
источник
case
я думал, операторы всегда должны быть постоянными значениями, иString.hashCode()
это не так (даже если на практике вычисления между JVM никогда не менялись).case
значения операторов не должны быть определяемыми во время компиляции, поэтому они работают нормально.В течение многих лет мы использовали препроцессор (с открытым исходным кодом) для этого.
Предварительно обработанные файлы называются Foo.jpp и обрабатываются в Foo.java с помощью скрипта ant.
Преимущество заключается в том, что он перерабатывается в Java, работающую на версии 1.0 (хотя обычно мы поддерживали только версию 1.4). Кроме того, это было намного проще сделать (много строковых переключателей) по сравнению с вымышлением с помощью перечислений или других обходных путей - код было намного легче читать, поддерживать и понимать. IIRC (на данный момент не может предоставить статистику или технические обоснования) также был быстрее, чем естественные эквиваленты Java.
Недостатки в том, что вы не редактируете Java, так что это немного больше рабочего процесса (редактировать, обрабатывать, компилировать / тестировать), плюс IDE свяжет обратно с Java, которая немного запутана (переключатель становится серией логических шагов if / else) и порядок переключения не поддерживается.
Я бы не рекомендовал его для версии 1.7+, но это полезно, если вы хотите программировать Java, которая предназначена для более ранних версий JVM (поскольку в Joe public редко устанавливаются последние версии).
Вы можете получить его из SVN или просмотреть код онлайн . Вам понадобится EBuild, чтобы построить его как есть.
источник
В других ответах говорилось, что это было добавлено в Java 7 и даны обходные пути для более ранних версий. Этот ответ пытается ответить на вопрос «почему»
Java была реакцией на чрезмерные сложности C ++. Он был разработан, чтобы быть простым чистым языком.
String получил немного особой обработки в этом языке, но мне кажется, что дизайнеры пытались свести к минимуму количество специальных оболочек и синтаксического сахара.
переключение струн довольно сложно под капотом, так как струны не являются простыми примитивными типами. Это не было обычной чертой в то время, когда была разработана Java, и она не очень хорошо вписывалась в минималистский дизайн. Тем более, что они решили не использовать специальный регистр == для строк, было бы (и бывает) немного странно, когда case работает, а == нет.
Между 1.0 и 1.4 сам язык оставался почти таким же. Большинство улучшений Java были на стороне библиотеки.
Все изменилось с Java 5, язык был значительно расширен. Дальнейшие расширения следовали в версиях 7 и 8. Я ожидаю, что это изменение отношения было вызвано ростом C #
источник
JEP 354. Выражения-переключатели (предварительный просмотр) в JDK-13 и JEP-361. Выражения-переключатели (стандартный) в JDK-14 расширяют оператор switch, чтобы его можно было использовать в качестве выражения .
Теперь вы можете:
case L ->
):Таким образом, демо из ответов ( 1 , 2 ) может выглядеть так:
источник
Не очень красиво, но вот другой способ для Java 6 и ниже:
источник
Это легкий ветерок в Groovy; Я встраиваю groovy jar и создаю
groovy
служебный класс, чтобы делать все это и многое другое, что я считаю раздражающим в Java (поскольку я застрял на Java 6 на предприятии).источник
Когда вы используете intellij также посмотрите на:
Файл -> Структура проекта -> Проект
Файл -> Структура проекта -> Модули
Если у вас есть несколько модулей, убедитесь, что вы установили правильный уровень языка на вкладке модуля.
источник
источник