繁体   English   中英

如何使用反射来调用具有原始参数的方法?

[英]How to use reflection to invoke a method with primitive arguments?

我正在尝试创建一个方法invokeMethod(String methodName, Object...args) ,它从当前实例的超类调用方法。 我尝试了以下实现。

    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();
        }
    }

这个实现的问题是如果我尝试用原始参数调用一个方法,我得到一个NoSuchMethodException因为它正在寻找一个方法,其参数的类型是等效的包装类。

例如,如果我尝试通过尝试invokeMethod("line", 50f, 50f, 50f, 50f)来调用带有签名line(float, float, float, float)的方法,我会得到一个类似于

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)

反正有没有让我的invokeMethod方法使用原始参数?

编辑: 这里的解决方案不起作用,因为在执行我的方法时,我不确切知道签名中的原始类型是什么。 我希望能够使用我的方法执行size(int, int)line(float, float ,float ,float)方法,并且链接中的解决方案不能轻松使用它。 我看到的唯一解决方案是为超类中的每个可能方法定义一个if语句,然后在链接中使用解决方案,但我想要一个不那么乏味的方法。

当诸如1010.0f类的参数传递给方法时,它们会自动换行,因为参数类型是Object...

因此,您需要检查这些包装类型并打开它们。 你的for循环可能如下所示:

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();
    }
}

我这里只添加了3个案例,你可以自己添加其他5个案例。

这意味着您现在无法使用包装类型参数调用方法。 如果你想打电话给那些,你需要

  1. 展开所有包装类型
  2. 尝试使用那些非包装类型查找方法
  3. 如果找不到,请再次将它们包起来
  4. 使用包装器类型找到一个方法。

编辑:

正如Holger在评论中建议的那样,您也可以让JVM通过使用找到合适的方法

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

Statement类的文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM