Есть ли что-нибудь вроде таблицы переходов / переходов в Java?

Есть ли в Java что-то похожее на таблицу переходов или переходов?

Таблица ветвления или таблицы переходов, согласно википедии,

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

Есть ли в Java что-то подобное или мне просто нужно использовать if/else if/else или case?

9 ответов

В Java есть оператор switch, но зависит от того, компилируется ли он в таблицу переходов в байт-коде. В общем, компиляторы создадут вам таблицу переходов, если они найдут хорошие константы для каждого случая в вашем операторе switch. Я не уверен, что вам должно быть все равно, как это реализовано. Если вы программируете на Java в первую очередь, вы, вероятно, просто прекрасно позволяете компилятору и JIT позаботиться об этом за вас.

Обратите внимание, что switch работает только с целочисленными примитивными типами и перечислениями, поэтому вам нужно использовать операторы if/else, если вы используете другие типы объектов (и вам, вероятно, в любом случае не следует сравнивать double или float для равенства).

Наконец, хотя ссылки на перечисления технически "постоянны", некоторые компиляторы генерируют таблицу переходов только при включении перечислений, если ваш оператор switch находится в том же модуле компиляции, где определено перечисление. В противном случае он сгенерирует вам цепочку if/else (как вы должны сделать для обычных объектов). Подробную информацию см. На форумах java.net по расширению использования переключателей для объектов.

Есть ли в Java что-то подобное или мне просто нужно использовать if/else if/else или case?

Я думаю, что операторы case (с переключателем в Java) эквивалентны.

Кроме того, в ООП переключатель может быть закодирован один раз, а затем разрешить полиморфизм для работы.

От: http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html

альтернативный текст

Это зависит от ваших требований.

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

Одним из способов передачи управления программой является вызов функции. Один из способов вызвать правильную функцию, когда у вас есть несколько вариантов выбора, - это отключить ее от типа объекта. Это называется полиморфизмом. Java и другие объектно-ориентированные языки имеют полиморфизм, реализуемый посредством наследования (подклассов). Не уверен, как это реализовано в Java, но в C++ есть (обычно? Или всегда?) Указатель в каждом объекте, который указывает на v-таблицу своего класса, которая содержит указатели на виртуальные функции.

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

Да, конечно.

Если вы кодируете оператор switch, то, в зависимости от различных вещей, ключ преобразуется в инструкцию tablewitch в байт-коде. В общем-то

  • Переключатель должен зависеть от значения int
  • Самое высокое значение int и самое низкое значение int не должны быть слишком далеко друг от друга

Самый простой способ добиться этого - использовать java-перечисления, которые специально обрабатываются компилятором. Соответствующая документация находится в Спецификации виртуальной машины Java. Конечно, JIT-компилятор почти наверняка преобразует их непосредственно в очень быстрые переключатели в машинном коде любой платформы, на которой вы работаете.

Сказав это, реальный ответ на ваш вопрос: "Это то, о чем вы беспокоитесь, когда пишете машинный код, а не программируете на языке высокого уровня".

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

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

Если вас действительно беспокоит производительность части вашего Java-приложения, вы можете переместить ее в код JNI и вообще обойти интерпретатор Java.

Я думаю, что именно так некоторые операторы switch реализуются, так сказать, "под капотом".

Кроме этого, вы могли бы сделать что-то подобное с чем-то вроде HashMap<whatever, Method>где вы используете map.get(something).invoke(), Но это своего рода побеждает цель, потому что она не будет такой же быстрой, как таблица переходов, и я не могу вспомнить хорошего случая, когда программирование / полиморфизм ООП не сделало бы работу лучше и чище.

Вы можете использовать enum для этого.

// doesn't work in c#
enum Switch implements Runnable {
   OPTION1() {
     public void run() {
        // do something.
     }
   },
   OPTION2() {
     public void run() {
        // do something.
     }
   },
   OPTION3() {
     public void run() {
        // do something.
     }
   }
}

Switch option = Switch.valueOf(switchOptionTest);
option .run();
//or
Switch[] options = Switch.values();
Switch option = options[nSwitchOption];
option .run();

Виды таблиц переходов / переходов, о которых вы говорите, не предоставляются непосредственно языками высокого уровня, такими как Java, C и т. Д., А генерируются компиляторами в машинном коде или байт-коде. Другими словами, ваш компилятор может использовать их, но вы их не видите.

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

Это действительно элегантно делать в C# из-за нативных анонимных методов, но не в Java.

Другие вопросы по тегам