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 NoSuchMethodException
porque 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 invokeMethod
mé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.
Cuando argumentos como 10
o 10.0f
se 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
- desenvolver todos los tipos de envoltura
- tratar de encontrar un método con esas tipos no contenedoras
- Si no lo encuentra, se envuelven de nuevo
- 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();