2010-04-05 2 views
15

Дано:Java getMethod с суперкласса параметров в методе

class A 
{ 
    public void m(List l) { ... } 
} 

Скажем, я хочу, чтобы вызвать метод m с отражением, передавая ArrayList в качестве параметра m:

List myList = new ArrayList(); 
A a = new A(); 
Method method = A.class.getMethod("m", new Class[] { myList.getClass() }); 
method.invoke(a, Object[] { myList }); 

getMethod на линии 3 будет вызывать NoSuchMethodException, потому что тип времени выполнения myList - это ArrayList, а не List.

Есть ли общий общий способ вокруг этого, который не требует знания типов параметров класса А?

ответ

18

Если вы знаете, что тип List, тогда используйте List.class в качестве аргумента.

Если вы не знаете тип заранее, представьте, что вы есть:

public void m(List l) { 
// all lists 
} 

public void m(ArrayList l) { 
    // only array lists 
} 

Какой метод следует отражение вызова, если есть автоматический способ?

Если вы хотите, вы можете использовать Class.getInterfaces() или Class.getSuperclass(), но это зависит от конкретного случая.

Что вы можете сделать здесь:

public void invoke(Object targetObject, Object[] parameters, 
     String methodName) { 
    for (Method method : targetObject.getClass().getMethods()) { 
     if (!method.getName().equals(methodName)) { 
      continue; 
     } 
     Class<?>[] parameterTypes = method.getParameterTypes(); 
     boolean matches = true; 
     for (int i = 0; i < parameterTypes.length; i++) { 
      if (!parameterTypes[i].isAssignableFrom(parameters[i] 
        .getClass())) { 
       matches = false; 
       break; 
      } 
     } 
     if (matches) { 
      // obtain a Class[] based on the passed arguments as Object[] 
      method.invoke(targetObject, parametersClasses); 
     } 
    } 
} 
+1

Мои мысли точно. –

+0

Я не знаю тип заранее. Я бы ожидал 'm2' в вашем примере, если мой l.getClass() возвращает ArrayList как тип времени выполнения, но, может быть, я ожидаю слишком многого? –

+0

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

1

Вместо myList.getClass(), почему бы не просто пройти в List.class? Это есть какой ваш метод ожидает.

+0

На самом деле я не знаю точно, какой метод вызывается. Существует не просто 'm', существует много методов с разными типами параметров. –

+1

Вам нужно знать априори, что вы собираетесь звонить. Отражение не похоже на магию. Вам нужно указать имя метода и подпись метода, к которым вы хотите получить доступ через отражение. Иногда вам также нужно знать, какую версию метода вам нужно вызвать (например, вам нужно получить доступ к версии метода «m», определенной одним из ваших суперклассов. –

+0

@luis: Я согласен с вашей точкой, говорящей рефлексию не поможет вам выбрать метод, но я не согласен с тем, что вам нужно знать априорный точный метод, который вы собираетесь вызывать. В контексте интерпретатора/динамического языка все, что у вас есть, это имя метода, аргументы и если вам повезет, у вас есть какая-то подсказка от пользователя. Разрыв между исходным материалом, предоставляемым API-интерфейсом отражения и выбором применимых методов на основе типов аргументов, должен быть обеспечен чем-то на уровне приложения-переводчика. –

1

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

+0

Спасибо, я знал об этом, но я не хотел прибегать к нему. Возможно, мне придется. –

2

См. Java.beans.Expression и java.beans.Statement.

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