【问题标题】:Using Class class getMethod() & reflection to find the correct method based on parameter types (with possible upcast)使用 Class 类 getMethod() 和反射根据参数类型找到正确的方法(可能向上转换)
【发布时间】:2021-05-16 11:07:37
【问题描述】:

我正在玩反射并尝试根据方法名称和提供的参数动态调用最适合的方法。我编写了一个简单的示例。给定方法名称和可接受的参数(或最终的几个参数),我可以确定要运行的正确方法吗?

正如你在这个例子中看到的......

public class Methods
{
    public static void goober(Object o) {
        System.out.println("Object");
    }

    public static void goober(Double d) {
        System.out.println("Double");
    }

    public static void goober(double d) {
        System.out.println("double");
    }
}

import java.lang.reflect.Method;
public class MethodIDTester
{
    public static void main(String[] args) {
        Methods.goober(new Object());    //prints Object                
        Methods.goober(new Double(5.0)); //prints Double        
        Methods.goober(5.0);             //prints double        
        Methods.goober(5);               //prints double        
        Methods.goober(new Integer(5));  //prints Object   
        System.out.println();

        invoker("Methods", "goober", new Object());    //prints Object             
        invoker("Methods", "goober", new Double(5.0)); //prints Double
        invoker("Methods", "goober", 5.0);             //prints Double - Not what I wanted
        invoker("Methods", "goober", 5);               //prints NoSuchMethodException - Not what I wanted
        invoker("Methods", "goober", new Integer(5));  //prints NoSuchMethodException - Not what I wanted
    }

    public static void invoker(String cName, String mName, Object param) {
        try {
            Class<?> c = Class.forName(cName);        
            Method m = c.getMethod(mName, param.getClass());
            m.invoke(c, param);
        } catch (Exception e) { System.out.println(e); }
    }

}

我如何改进我的调用程序,以便它以与 java 在我直接调用方法时相同的方式将参数连接到正确的方法?

我希望参数 5.0 位于接收原始双精度的方法中。

我希望它意识到原始 int 5 可以落在接收双精度值的方法中。

我希望它意识到 Integer 对象可以落在接收 Object 对象的方法中。

我在尝试编写自己的向上转换系统时犹豫不决,因为我不一定知道 java 如何确定向上转换的优先级(尤其是当有多个参数时)。我想确保我的系统识别出编译器会识别的相同方法,这似乎很危险。我宁愿只问 java 它会使用哪种方法 bind 而不是自己弄清楚。有这样的东西吗?

【问题讨论】:

  • invoker 无法判断您传递给它的是double 还是Double,因此它无法区分应该使用哪种方法。
  • 向上转换的问题呢?当 param 为 new Integer(5) 无法实现 param 可以传递给 goober(Object o)
  • 看看java.beans.Expression。可能更容易使用。

标签: java reflection invoke getmethod


【解决方案1】:

反射查找与方法的精确声明相匹配,这就是某些查找返回 NoSuchMethodException 的原因。如果找不到方法,您可以尝试查看超类。

Method m = c.getMethod(mName, param.getClass());

对于调用者调用,double 值自动装箱为 Double,因此处理 Double / double 大小写的唯一方法是将调用者更改为提供 double.class。

要解决这两个问题,您可以添加 invoker() 以查找 Class,例如:

public static void invoker(String cName, String mName, Object param) {
    invoker(cName, mName, param.getClass(), param);
}
public static void invoker(String cName, String mName, Class<?> argC,  Object param)    {
    try {
        Class<?> c = Class.forName(cName);
        System.out.println("invoker "+cName+"."+mName+"("+argC.getName()+") with param "+param);
        Method m = c.getMethod(mName, argC);
        m.invoke(c, param);
    }
    catch (NoSuchMethodException e) {
        Class<?> sup = argC.getSuperclass();
        if (sup != null)
            invoker(cName, mName, sup, param);
    }
    catch (Exception e) {
        System.out.println(e);
    }
}

然后:

invoker("Methods", "goober", new Double(5.0));   //prints Double
invoker("Methods", "goober", 5.0);               //prints Double as before
invoker("Methods", "goober", double.class, 5.0); //prints double

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 2011-04-05
    • 1970-01-01
    相关资源
    最近更新 更多