Почему ваш тип данных оператора switch не может быть длинным, Java? - PullRequest
72 голосов
/ 20 апреля 2010

Вот выдержка из Обучающих программ Sun по Java :

Коммутатор работает с примитивными типами данных byte, short, char и int. Он также работает с перечисляемыми типами (обсуждается в классах и наследовании) и несколькими специальными классами, которые «обертывают» определенные примитивные типы: Character, Byte, Short и Integer (обсуждается в простых объектах данных).

Должна быть веская причина, по которой примитивный тип данных long не допускается. Кто-нибудь знает, что это такое?

Ответы [ 4 ]

45 голосов
/ 20 апреля 2010

Я думаю, что в некоторой степени это было произвольное решение, основанное на типичном использовании коммутатора.

Переключатель, по сути, может быть реализован двумя способами (или, в принципе, комбинацией): для небольшого числа случаев или случаев, значения которых широко рассеяны, переключатель по существу становится эквивалентом серии ifs на временной переменная (включаемое значение должно оцениваться только один раз). Для небольшого числа случаев, более или менее последовательных по значению, используется таблица переключателей (инструкция TABLESWITCH в Java), в результате чего местоположение, к которому нужно перейти, эффективно ищется в таблице.

Любой из этих методов может в принципе использовать длинное значение, а не целое число. Но я думаю, что это было, вероятно, просто практическое решение, чтобы сбалансировать сложность набора команд и компилятора с реальной потребностью: случаи, когда вам действительно нужно переключиться на длинную, достаточно редки, поэтому приемлемо переписать как последовательность операторов IF или обходной цикл каким-либо другим способом (если длинные значения, о которых идет речь, близки друг к другу, вы можете в своем коде Java переключить результат int, вычитая наименьшее значение).

18 голосов
/ 20 апреля 2010

Поскольку они не реализовали необходимые инструкции в байт-коде, и вы действительно не хотите писать так много случаев, независимо от того, насколько "готов к производству" ваш код ...

[РЕДАКТИРОВАТЬ: Извлечено из комментариев к этому ответу, с некоторыми добавлениями на фоне]

Если быть точным, 2³² - это лот дел, и любая программа с методом, достаточно длинным, чтобы вместить больше, будет ужасно ужасна! На любом языке. (Самая длинная функция, которую я знаю в любом коде на любом языке, - это немногим более 6 тыс. SLOC - да, это большой switch - и он действительно неуправляем.) Если вы действительно застряли с long, где вам следует иметь только int или меньше, тогда у вас есть две реальные альтернативы.

  1. Используйте некоторый вариант темы хеш-функций, чтобы сжать long в int. Самый простой, только для использования, когда у вас неправильный тип, это просто разыграть! Более полезным было бы сделать это:

    (int) ((x&0xFFFFFFFF) ^ ((x >>> 32) & 0xFFFFFFFF))
    

    до включения результата. Вы должны будете решить, как преобразовать случаи, с которыми вы тоже тестируете. Но на самом деле, это все еще ужасно, поскольку не решает реальную проблему многих случаев.

  2. Гораздо лучшее решение, если вы работаете с очень большим количеством дел, - это изменить свой дизайн на использование Map<Long,Runnable> или чего-то подобного, чтобы вы искали способ передачи определенного значения. Это позволяет вам разделять наблюдения на несколько файлов, что значительно упрощает управление, когда количество обращений становится большим, хотя становится сложнее организовать регистрацию хоста участвующих классов реализации (аннотации могут помочь, позволив вам создайте регистрационный код автоматически).

    FWIW, я делал это много лет назад (мы перешли на недавно выпущенный J2SE 1.2 в рамках проекта), когда создавал собственный механизм байт-кода для симуляции массивно-параллельного оборудования (нет, повторное использование JVM не было бы подходящим из-за радикально отличающихся задействованных моделей значения и исполнения), и это чрезвычайно упростило код относительно большой switch, которую использовала версия кода на C.

Повторение сообщения о возврате домой, желание switch на long является признаком того, что в вашей программе неправильно указаны типы или что вы строите систему с таким большим количеством изменений, что Вы должны использовать классы. Время для переосмысления в любом случае.

3 голосов
/ 20 апреля 2010

Поскольку индекс таблицы поиска должен быть 32 бита.

0 голосов
/ 20 апреля 2010

Длинный в 32-битных архитектурах представлен двумя словами . А теперь представьте, что может произойти, если из-за недостаточной синхронизации выполнение оператора switch наблюдает long с его старшими 32 битами из одной записи и 32 младшими из другой! Он может попытаться пойти в .... кто знает где! В основном где-то наугад. Даже если обе записи представляют действительные случаи для оператора switch, их забавная комбинация, вероятно, не приведет ни к первому, ни ко второму - или, что еще хуже, может привести к другому действительному, но не связанному случаю!

По крайней мере, с int (или меньшими типами), независимо от того, как сильно вы запутались, оператор switch будет по крайней мере читать значение, которое кто-то на самом деле написал , вместо значения "из тонкого воздух».

Конечно, я не знаю действительной причины (прошло более 15 лет, я так долго не обращал внимания!), Но если вы поймете, насколько небезопасной и непредсказуемой может быть такая конструкция, вы ' Я согласен, что это определенно очень веская причина не когда-либо иметь переключатель на long (и, как предполагалось, long-pun - будут 32-битные машины, эта причина будет действительной) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...