Llamar a los métodos estáticos de un objeto java/groovy usando la reflexión

Estoy trabajando en una maravillosa clase de prueba unitaria que contiene una colección de reglas para determinar si el contenido de un archivo tiene el formato correcto o no. (Al no usar un motor de reglas adecuado, simplemente aprovecha las capacidades de aserción de Groovy para realizar la validación de una manera que se asemeja vagamente a lo que haría un motor de reglas). Estaba pensando que podría crear un método llamado FireAllRules que se vea así:

public static void FireAllRules(File file)
{
    for(def method in Class.getMethods)
    {
        if(method.name.indexOf("rule" == 0) method.invoke(file);
    }
}

Todos los métodos que quiero que el ciclo tome en cuenta son estáticos, y noté durante el proceso de depuración que ninguno de mis métodos de regla está incluido en la enumeración Class.getMethods(). Idealmente, me gustaría recorrer solo los métodos que escribí personalmente en la clase en lugar de clasificar docenas de métodos poco interesantes que vienen junto con java.Object. ¿Hay alguna manera de usar la reflexión para iterar sobre estos métodos estáticos en tiempo de ejecución?

preguntado el 03 de mayo de 12 a las 20:05

3 Respuestas

Dado:

class Test {
  public static testThis() {
    println "Called testThis"
  }

  public static woo() {
    println "Called woo"
  }

  public static testOther() {
    println "Called testOther"
  }
}

Tu puedes hacer:

Test.metaClass.methods.grep { it.static && it.name.startsWith( 'test' ) }.each {
  it.invoke( Test )
}

Imprimir:

Called testOther
Called testThis

Un método más genérico para ejecutar los métodos de prueba estáticos de una clase sería:

def invokeClass( clazz ) {
  clazz.metaClass.methods.grep { it.static && it.name.startsWith( 'test' ) }.each {
    it.invoke( clazz )
  }
}

invokeClass( Test )

contestado el 03 de mayo de 12 a las 20:05

Esto se parece exactamente a lo que tenía en mente. El único problema con el que me encuentro es que el compilador se queja de que it.invoke(clazz) tiene el número incorrecto de argumentos. ¿Sabes por qué puede ser eso? EDITAR: No importa, lo tengo. - Estanford

@estanford Podrías intentarlo it.invoke( clazz, null ) Curiosamente, la versión de un solo argumento me funciona... ¿qué versión de Groovy? 1.8.6? - tim_yates

@tim_yates Noté que su ejemplo era diferente al mío en la medida en que estaba pasando un objeto File a todas las reglas y su ejemplo no, así que tuve que llamar al método de invocación como it.invoke(clazz, file) para que funcione correctamente. - Estanford

@estanford ahhh sí... Lo siento, lo olvidé originalmente cuando se me ocurrió el código de arriba :-( ¡Me alegro de que lo hayas solucionado! :-) - tim_yates

Los métodos estáticos se incluyen en los métodos devueltos por getMethods(). Su problema podría ser method.name.indexOf("rule" == 0). Esto debería ser method.name.indexOf("rule") == 0, o mejor aún method.name.startsWith("rule").

Además, ¿son públicos sus métodos de regla? Si no, puedes usar getDeclaredMethods(). Para invocarlos, tendrás que llamar setAccessible() de antemano.

contestado el 03 de mayo de 12 a las 20:05

La versión de Java sería algo como esto (he eliminado las importaciones y excepciones para mayor claridad).

public class FindAndRunStaticMethods {
    public static void main(String[] args) {
        fireAllRules();
    }

    public static void fireAllRules() {
        for(Method method : StaticMethodClass.class.getDeclaredMethods()) {
            findAndRunRules(method);
        }
    }

    private static void findAndRunRules(Method method) {
        if (!Modifier.isStatic(method.getModifiers())) return;
        if (!method.getName().startsWith("rule")) return;
        if (!method.getReturnType().equals(Void.TYPE)) return;

        Class[] parameterTypes = method.getParameterTypes();

        if (parameterTypes.length != 1) return;
        if (!parameterTypes[0].equals(File.class)) return;

        method.invoke(null, new File("dummy"));
    }
}

Una clase de prueba de muestra podría verse así

public class StaticMethodClass {
    public static void ruleHere(File x) { System.out.println("should print"); }
    public static void ruleRun(File x) { System.out.println("should print"); }  
    public void ruleNotSelected() { System.out.println("not run"); }
}

contestado el 11 de mayo de 12 a las 01:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.