Как я могу отобразить Строку на функцию в Java?

В настоящее время у меня есть набор классов Java та реализация a Processor интерфейс, имея в виду у них всех есть a processRequest(String key) метод. Идея состоит в том, что каждый класс имеет некоторых (скажите, <10), участник Strings, и каждая из тех карт к методу в том классе через processRequest метод, как так:

class FooProcessor implements Processor
{
    String key1 = "abc";
    String key2 = "def";
    String key3 = "ghi";
    // and so on...

    String processRequest(String key)
    {
        String toReturn = null;
        if (key1.equals(key)) toReturn = method1();
        else if (key2.equals(key)) toReturn = method2();
        else if (key3.equals(key)) toReturn = method3();
        // and so on...

        return toReturn;
    }

    String method1() { // do stuff }
    String method2() { // do other stuff }
    String method3() { // do other other stuff }
    // and so on...
}

Вы получаете идею.

Это хорошо работало для меня, но теперь мне нужно доступное для времени выполнения отображение от ключа до функции; не каждая функция на самом деле возвращает Строку (некоторый возврат пусто), и я должен динамично получить доступ к типу возврата (использующий отражение) каждой функции в каждом классе, что существует ключ для. У меня уже есть менеджер, который знает обо всех ключах, но не отображении от ключа до функции.

Мой первый инстинкт должен был заменить это использование отображения if-else операторы с a Map<String, Function>, как я мог сделать в JavaScript. Но, Java не поддерживает первоклассные функции, таким образом, мне не повезло там. Я мог, вероятно, вскопать стороннюю библиотеку, которая позволяет мне работать с первоклассными функциями, но я еще не видел никого, и я сомневаюсь, что мне нужна вся новая библиотека.

Я также думал о помещении их String ключи в массив и использование отражения для вызова методов по имени но я вижу две оборотных стороны к этому методу:

  • Мои ключи нужно было бы назвать тем же как метод - или назвать конкретным, последовательным способом так, чтобы было легко отобразить их на имя метода.
  • Это кажется ПУТЕМ медленнее, чем if-else операторы я имею прямо сейчас. Эффективность является чем-то вроде беспокойства, потому что эти методы будут иметь тенденцию называться довольно часто, и я хочу минимизировать ненужные издержки.

TL; DR: я ищу чистый, минимально-служебный путь к карте a String к своего рода a Function возразите, что я могу вызвать и звонить (что-то как) getReturnType() на. Я особенно не возражаю пользоваться сторонней библиотекой, если она действительно соответствует моим потребностям. Я также не возражаю использовать отражение, хотя я сильно предпочел бы избегать использования отражения каждый раз, когда я делаю поиск метода - возможно, использующий некоторую кэширующуюся стратегию, которая объединяется Map с отражением.

Мысли о хорошем способе получить то, что я хочу?Удачи!

11
задан Matt Ball 30 April 2010 в 15:49
поделиться

6 ответов

А как насчет класса Method из API отражения? Вы можете найти методы класса по имени, параметрам или типу возвращаемого значения. Затем вы просто вызываете Method.invoke (this, parameters).

Это почти то же самое, что и карта из JavaScript, о которой вы говорите.

0
ответ дан 3 December 2019 в 08:54
поделиться

Этот example использует enum именованных функций и абстрактный FunctionAdapter для вызова функций с переменным числом однородных параметров без отражения. Функция lookup() просто использует Enum.valueOf, но Map может стоить того для большого количества функций.

1
ответ дан 3 December 2019 в 08:54
поделиться

Как вы заметили, вы можете делать то, что хотите, используя Reflection API, но вы теряете некоторые преимущества компилятора Java, в дополнение к проблемам, которые вы уже придумали. Решит ли ваша проблема с переносом Strings в объект и использование шаблона Visitor? Каждый StringWrapper принимает только Посетитель, у которого есть правильный метод, или что-то в этом роде.

0
ответ дан 3 December 2019 в 08:54
поделиться

Используйте Map, где ключ - строка, а значение - объект, реализующий интерфейс, содержащий method(). Таким образом, вы можете получить из карты объект, содержащий нужный вам метод. Затем просто вызовите этот метод на объекте. Например:

class FooProcessor implements Processor{

    Map<String, FooMethod> myMap;

    String processRequest(String key){
        FooMethod aMethod = myMap.getValue(key);
        return aMethod.method();
    }        
}
0
ответ дан 3 December 2019 в 08:54
поделиться

Не существует первоклассных самостоятельных функций, но вы можете делать все, что хотите, с помощью интерфейса. Создайте интерфейс, который представляет вашу функцию. Например, у вас может быть следующее:

public interface ComputeString
{
    public String invoke();
}

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

7
ответ дан 3 December 2019 в 08:54
поделиться

Хотя вы не можете иметь функции первого класса, есть анонимные классы, которые могут быть основаны на интерфейсе:

interface ProcessingMethod {
   String method();
}

Map<String, ProcessingMethod> methodMap = new HashMap<String, ProcessingMethod>();
methodMap.put("abc", new ProcessingMethod() {
   String method() { return "xyz" }
});
methodMap.put("def", new ProcessingMethod() {
   String method() { return "uvw" }
});

methodMap.get("abc").method();

Или вы можете использовать Scala :-)

4
ответ дан 3 December 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: