Я думаю, что в некоторой степени это было, вероятно, произвольное решение, основанное на типичном использовании переключателя.
Переключатель может быть реализован двумя способами (или, в принципе, комбинацией): для небольшого числа случаев или тех, чьи значения сильно различаются, переключатель по существу становится эквивалентом серии if для временной переменной ( включаемое значение следует оценивать только один раз). Для умеренного числа случаев, которые являются более или менее последовательными по значению, используется таблица переключения (инструкция TABLESWITCH в Java), посредством которой место перехода эффективно ищется в таблице.
Любой из этих методов в принципе может использовать длинное значение, а не целое число. Но я думаю, что это было, вероятно, просто практическое решение сбалансировать сложность набора инструкций и компилятора с реальной потребностью: случаи, когда вам действительно нужно переключаться на долгое время, достаточно редки, и их можно переписать как последовательность операторов IF или обойтись каким-либо другим способом (если рассматриваемые длинные значения близки друг к другу, вы можете в своем коде Java переключить результат int вычитания наименьшего значения).
Потому что они не реализовали необходимые инструкции в байт-коде, и вы действительно не хотите писать так много случаев, независимо от того, насколько ваш код «готов к производству» ...
[РЕДАКТИРОВАТЬ: извлечено из комментариев к этому ответу, с некоторыми дополнениями в фоновом режиме]
Если быть точным, 2³² - это очень много случаев, и любая программа с методом, достаточно длинным, чтобы вместить больше, будет совершенно ужасной! На любом языке. (Самая длинная функция, о которой я знаю в любом коде на любом языке, составляет чуть более 6 тыс. SLOC - да, это большой
switch
- и действительно неуправляемый.) Если вы действительно застряли в том, чтобы иметь место,long
где у вас должно быть толькоint
или меньше, тогда у вас есть две реальные альтернативы.Используйте какой-нибудь вариант на тему хэш-функций, чтобы сжать файл
long
в форматеint
. Самый простой способ, который можно использовать только тогда, когда у вас неправильный тип, - это просто приведение! Полезнее было бы сделать так:(int) ((x&0xFFFFFFFF) ^ ((x >>> 32) & 0xFFFFFFFF))
до включения результата. Вам также придется подумать, как преобразовать кейсы, против которых вы тестируете. Но на самом деле это все еще ужасно, поскольку во многих случаях это не решает настоящую проблему.
Гораздо лучшим решением, если вы работаете с очень большим количеством кейсов, является изменение вашего дизайна на использование
Map<Long,Runnable>
или чего-то подобного, чтобы вы искали, как отправить конкретное значение. Это позволяет вам разделять дела на несколько файлов, что намного проще контролировать, когда количество дел становится большим, хотя становится сложнее организовать регистрацию хоста задействованных классов реализации (аннотации могут помочь, позволяя вам создать регистрационный код автоматически).FWIW, я сделал это много лет назад (мы перешли на недавно выпущенный J2SE 1.2 в ходе реализации проекта) при создании собственного механизма байт-кода для моделирования массивно-параллельного оборудования (нет, повторное использование JVM было бы неприемлемым из-за радикального различные модели значений и исполнения), и это значительно упростило код по сравнению с тем,
switch
что использовала версия кода C.Повторим Забирать домой сообщение, желая
switch
наlong
это признак того, что либо у вас есть типы неправильно в вашей программе или что вы создаете систему с этим много вариаций вовлеченного , что вы должны использовать классы. В любом случае время для переосмысления.источник
Map<Long,Runnable>
чтобы решить проблему совершенно другим способом. :-)switch
? Желание сделать выбор в пользу ограниченного набора из такого количества элементов просто указывает на ошибку в фундаментальном дизайне программы. То, что люди просят об этом, просто означает, что ** они ошиблись в дизайне .long
количество строк, мне, в частности, нужно только 4. Это случай, когда мнеlong
передают руку, которая указывает, какая строка обрабатывается, и мне нужно делать разные вещи в зависимости от того, какая это строка. Думаю, я мог бы привести к int, но это облегчило бы мою жизнь, если бы я мог простоswitch
использовать переменную. Как бы то ни было, я просто использую строку изif
иelse if
.long
не означает, что вы собираетесь проверить все возможности, точно так же, как наличиеint
илиString
не означает этого. Это означает, что значения, которые у вас есть, которых может быть несколько, имеют большой диапазон . Вы можете проверить несколько простых случаев и попробоватьdefault
остальные. Необходимость выполнять сдвиги и преобразования означает, что вы рискуете потерять данные. В итоге, это плохое дизайнерское решение Java, а не проблема пользователя.Потому что индекс таблицы поиска должен быть 32 бита.
источник
switch
необязательно реализовывать справочную таблицу.В 32-битной архитектуре long обозначается двумя словами . А теперь представьте, что могло бы случиться, если бы из-за недостаточной синхронизации выполнение оператора switch наблюдало бы long с его старшими 32 битами от одной записи, а 32 младшими - с другой! Он мог бы попытаться пойти… кто знает куда! В основном где-то наугад. Даже если обе записи представляют допустимые случаи для оператора switch, их забавная комбинация, вероятно, не приведет ни к первому, ни ко второму - или, что еще хуже, это может привести к другому допустимому, но не связанному с ним случаю!
По крайней мере, с int (или меньшими типами), независимо от того, насколько сильно вы напортачили, оператор switch по крайней мере прочитает значение, которое кто-то на самом деле написал , а не значение «из воздуха».
Конечно, я не знаю истинной причины (прошло уже более 15 лет, я так давно не обращал внимания!), Но если вы понимаете, насколько небезопасной и непредсказуемой может быть такая конструкция, вы согласитесь, что это определенно очень хорошая причина, чтобы никогда не включать longs (и, как и предполагалось long -pun, будут 32-битные машины, эта причина останется в силе).
источник
if
и результат будет таким же плохим: неправильный результат ~> выбрана неправильная ветка. Создание длинногоif
-else
-if
цепь вместо того , чтобыswitch
фактически приведет к точно такому же результату.