Cómo utilizar la reflexión para invocar un método con argumentos primitivos?

Lind tormenta:

Estoy tratando de crear un método invokeMethod(String methodName, Object...args)que invoca un método de una superclase en la instancia actual. He intentado el siguiente aplicación.

    public void invokeMethod(String methodName, Object...args) {
        //Array to hold the classes of the arguments
        Class<?>[] classes = new Class<?>[args.length]; 
        //Initialize each class in the array to the class of each argument 
        for(int i = 0; i < args.length; i++)
            classes[i] = args[i].getClass();
        try {
            //find the method
            Method m = this.getClass().getMethod(methodName, classes);
            //invoke the method
            m.invoke(this, args);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

El problema de esta aplicación es que si trato de invocar un método con parámetros primitivos, aparece un NoSuchMethodExceptionporque está buscando un método con parámetros cuyo tipo es el equivalente clase contenedora.

Por ejemplo, si trato de invocar un método con la firma line(float, float, float, float)por tratar invokeMethod("line", 50f, 50f, 50f, 50f), recibo una excepción similar a

java.lang.NoSuchMethodException: DynamicSketch.line(java.lang.Float, java.lang.Float, java.lang.Float, java.lang.Float)
at java.base/java.lang.Class.getMethod(Class.java:2109)
at DynamicSketch.invokeMethod(DynamicSketch.java:32)
at DynamicSketch.setup(DynamicSketch.java:19)
at processing.core.PApplet.handleDraw(PApplet.java:2412)
at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:316)

¿Hay alguna forma para que mi invokeMethodmétodo de trabajo con argumentos primitivos?

Editar: La solución aquí no funciona porque no sé exactamente qué tipos primitivos están en la firma al ejecutar mi método. Quiero ser capaz de ejecutar métodos como size(int, int)y line(float, float ,float ,float)usando mi método, y la solución en el enlace no funciona fácilmente con este. La única solución que veo a esto es definir una sentencia if para todos los métodos posibles en la superclase y luego usar la solución en el enlace, pero yo quería una forma menos tedioso.

barredora:

Cuando argumentos como 10o 10.0fse pasan en el método, se envuelven de forma automática, debido a que el tipo de parámetro es Object....

Por lo tanto, es necesario comprobar para este tipo de envoltura y desenvolver. Su lazo para puede tener este aspecto:

for(int i = 0; i < args.length; i++) {
    if (args[i].getClass() == Integer.class) {
        classes[i] = int.class;
    } else if (args[i].getClass() == Float.class) {
        classes[i] = float.class;
    } else if (args[i].getClass() == Double.class) {
        classes[i] = double.class;
    } else {
        classes[i] = args[i].getClass();
    }
}

Sólo he añadido 3 casos aquí, se puede añadir otro 5 a ti mismo.

Esto significa que no se puede llamar a los métodos con argumentos de tipo envoltura ahora. Si desea llamar a esos también, es necesario

  1. desenvolver todos los tipos de envoltura
  2. tratar de encontrar un método con esas tipos no contenedoras
  3. Si no lo encuentra, se envuelven de nuevo
  4. encontrar un método utilizando los tipos de contenedor.

Editar:

Como Holger sugerido en los comentarios, también puede dejar que la JVM encontrar un método adecuado para que, mediante el uso de

new Statement(this, methodName, args).execute();

Documentos para la Statementclase.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=204910&siteId=1
Recomendado
Clasificación