Ответ 1
Не могли бы вы сделать String
в Method
? Затем вы можете кэшировать методы, необходимые для выполнения.
В настоящее время у меня есть куча классов Java, которые реализуют интерфейс Processor
, то есть все они имеют метод 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...
}
Вы получаете идею.
Это работало отлично для меня, но теперь мне нужно доступное время исполнения от ключа к функции; не каждая функция фактически возвращает String (некоторый возврат void), и мне нужно динамически обращаться к типу return (используя отражение) каждой функции в каждом классе, для которой есть ключ. У меня уже есть менеджер, который знает обо всех ключах, но не в отображении от ключа к функции.
Мой первый инстинкт заключался в замене этого сопоставления с помощью операторов if-else
с помощью Map<String, Function>
, как я мог бы сделать в Javascript. Но Java не поддерживает первоклассные функции, поэтому мне там не повезло. Возможно, я мог бы выкопать стороннюю библиотеку, которая позволяет мне работать с первоклассными функциями, но я еще не видел их, и я сомневаюсь, что мне нужна вся новая библиотека.
Я также думал о том, чтобы поместить эти ключи String
в массив и использовать отражение для вызова методов по имени, но я вижу два нижних уровня этого метода:
if-else
, которые у меня есть сейчас. Эффективность - это что-то вроде проблемы, потому что эти методы будут часто вызываться довольно часто, и я хочу минимизировать ненужные накладные расходы. TL; DR: Я ищу чистый, минимальный накладной способ сопоставления String
с каким-либо объектом Function
, который я могу вызвать и вызвать (что-то вроде) getReturnType()
on. Я не особо возражаю против использования сторонней библиотеки, если она действительно соответствует моим потребностям. Я также не возражаю против использования рефлексии, хотя я бы предпочел не использовать рефлексию каждый раз, когда я выполняю поиск метода - возможно, используя некоторую стратегию кэширования, которая объединяет Map
с отражением.
Мысли о хорошем способе получить то, что я хочу? Ура!
Не могли бы вы сделать String
в Method
? Затем вы можете кэшировать методы, необходимые для выполнения.
Нет никаких автономных функций первого класса, но вы можете делать то, что хотите, с помощью интерфейса. Создайте интерфейс, который представляет вашу функцию. Например, у вас может быть следующее:
public interface ComputeString
{
public String invoke();
}
Затем вы можете создать объект Map<String,ComputeString>
, как вы хотите, в первую очередь. Использование карты будет намного быстрее, чем отражение, а также даст больше безопасности типов, поэтому я бы посоветовал выше.
Пока у вас нет функций первого класса, существуют анонимные классы, которые могут быть основаны на интерфейсе:
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: -)
Как вы заметили, вы можете делать то, что хотите, используя Reflection API, но вы потеряете некоторые преимущества компилятора Java, в дополнение к проблемам, которые вы уже придумали. Обертывание ваших строк в объекте и использование Шаблон посетителя разрешит вашу проблему? Каждый StringWrapper
принимает только Visitor
, который имеет правильный метод или что-то в этом роде.
Используйте карту, где ключ является строкой, а значение - это объект, реализующий интерфейс, содержащий метод(). Таким образом вы можете получить объект, содержащий метод, который вы хотите, из карты. Затем просто вызовите этот метод на объекте. Например:
class FooProcessor implements Processor{
Map<String, FooMethod> myMap;
String processRequest(String key){
FooMethod aMethod = myMap.getValue(key);
return aMethod.method();
}
}
Этот пример использует enum
названных функций и абстрактный FunctionAdapter
для вызова функций с переменным числом однородных параметров без отражение. Функция lookup()
просто использует Enum.valueOf
, но Map
может стоить большого количества функций.
Как насчет Method класс из API отражения? Вы можете найти методы класса на основе имени, параметров или типа возврата. Затем вы просто вызываете Method.invoke(это, параметры).
Это почти то же самое, что и карта с JavaScript, о которой вы говорите.