2010-04-05 15 views
15

Teniendo en cuenta:Java getMethod con los parámetros de la superclase en el método

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

Digamos que quiero invocar el método m con la reflexión, que pasa a un ArrayList como parámetro a m:

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

El getMethod on line 3 lanzará NoSuchMethodException porque el tipo de tiempo de ejecución de myList es ArrayList, no List.

¿Existe una buena forma genérica que no requiera el conocimiento de los tipos de parámetros de clase A?

Respuesta

18

Si sabe que el tipo es List, utilice List.class como argumento.

Si no conoce el tipo de antemano, imagina que tienes:

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

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

Qué método debería invocar la reflexión, si hay alguna manera automática?

Si lo desea, puede usar Class.getInterfaces() o Class.getSuperclass(), pero esto es específico de cada caso.

Lo que puede hacer aquí es:

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

Mis pensamientos exactamente. –

+0

No sé el tipo por adelantado. Esperaría 'm2' en su ejemplo si mi l.getClass() devuelve ArrayList como el tipo de tiempo de ejecución, pero ¿tal vez estoy esperando demasiado? –

+0

exactamente. Pero desea ejecutar el primer método dependiendo de si el segundo existe o no. No puedes hacer eso. – Bozho

1

En lugar de myList.getClass(), ¿por qué no pasar en List.class? Eso es lo que su método está esperando.

+0

Realmente no tengo conocimiento de exactamente qué método se está llamando. No hay solo 'm', hay muchos métodos con diferentes tipos de parámetros. –

+1

Necesita saber a priori a qué llamará. La reflexión no es como magia. Necesita a qué nombre de método y firma de método desea acceder a través de la reflexión. A veces también necesitas saber qué versión de un método necesitas llamar (es decir, necesitas acceder a la versión de un método 'm' definido por una de tus súper clases. –

+0

@luis: estoy de acuerdo con tu punto de decir reflexión no lo ayudará a elegir un método, pero no estoy de acuerdo con que necesite saber a priori a qué método exacto va a llamar. En un contexto de lenguaje de intérprete/dinámico, todo lo que tiene es un nombre de método, argumentos y si tiene suerte, tiene algún tipo de sugerencia del usuario. La brecha entre la materia prima proporcionada por la API de reflexión y la elección de los métodos aplicables basados ​​en tipos de argumentos debe ser proporcionada por algo en el nivel de aplicación del intérprete –

1

supongo que desea getDeclaredMethods(). Aquí hay un example. Puede profundizar en la lista de métodos y elegir el que desee por su nombre. Si esto es robusto o una buena idea es otra pregunta.

+0

Gracias, lo sabía pero no quería recurrir a él. Aunque podría tener que hacerlo. –

2

Consulte java.beans.Expression y java.beans.Statement.

Cuestiones relacionadas