2010-08-24 4 views
3

Прежде всего позвольте мне сказать, что я поддерживаю плохо разработанный код другого человека, поэтому я ограничен тем, насколько могу его изменить.Отражение Java, где параметр метода является интерфейсом

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

Вот проблема: я получаю исключение NoSuchMethodException, потому что он ищет метод с Hashtable в качестве аргумента, даже если Hashtable реализует интерфейс Map. Меня смущает то, что если я не буду использовать отражение (основное изменение дизайна в этом случае) и передал Hashtable, он будет ссылаться на метод с параметром Map - так почему же он не работает одинаково, когда я использую отражение ?

Учитывая, что я в значительной степени должен придерживаться рефлексии, есть ли способ получить метод с аргументом Map для вызова, когда я передаю ему класс, реализующий этот интерфейс?

Если вы хотите, я могу издеваться код до демонстрации ...

ответ

4

Если вы используете getMethod(String name, Class[] parameterTypes) из java.lang.Class, вам необходимо указать типы параметров, выраженные в сигнатуре метода интерфейса (статический тип), а не тип объекта во время выполнения (динамический тип).

Так, methodXyz(Map map), вместо:

Method m = cl.getMethod("methodXyz", new Class[]{argument.getClass()}); 

сделать это:

Method m = cl.getMethod("methodXyz", new Class[]{Map.class}); 
+0

Проблема существует около 20 методов называемых methodXyz с различными аргументами, которые работают очень хорошо. Только этот новый принимает карту как аргумент, вызывающий проблемы. Я могу сделать то, что вы говорите, но это требует, чтобы я определил, является ли данный параметр Картой с использованием, например, instanceof :) Я не понимаю, почему отражение не работает так же, как не отраженный код, когда поиск методов?!?! Он должен использовать совершенно другой механизм, я думаю ... – BigMac66

+0

getMethod() ожидает точных типов определения.Вот почему он называется getMethod(), а не findMethod(). Вы можете написать свой собственный метод findMethod(), если вы часто отправляете динамический метод. Это предполагает поиск методов, имеющих имя proprer, фильтрацию того, где параметры не совместимы с данными аргументами, и касается случаев, когда более одного метода остается кандидатом, например. следующий случай является неоднозначным и является ошибкой компиляции: new StringBuffer(). append (null). – gawi

1

У меня была аналогичная проблема. Я вижу 2 решения:

решение 1: вы можете разработать более сложный метод поиска.

Пример алгоритма можно использовать:

You search with the parameter type. If the search fails (Exception), but one of the parameters has a super type (or implements an interface), you search the same method name, but with this superclass (or interface). You throw the exception only if no method is found after this search algorithm.

Примечание: если ваши методы имеют несколько параметров, не забудьте проверить с каждой возможной комбинации супертипов/интерфейсов. Это может привести к довольно сложному алгоритму поиска ...

решение 2: другим способом, намного проще, является точный выбор типов отдельно от параметров. Этот метод более подробный может быть необходим, если вы хотите использовать нулевые параметры.

Таким образом, "InvokeMethod (String имяМетода, Object [] paramters)" становится "InvokeMethod (String имяМетода, Class [] methodParamTypes, Object [] параметры)".

Смежные вопросы