作为开发一个小ScriptEngine的一部分,我反思地调用java方法。脚本引擎的调用为我提供了方法名称和参数数组的对象。要调用方法,我尝试通过调用Class.getMethod(名称,参数类型)来解决它 但是,只有当参数的类和Method预期的类相同时,才能使用它。
Object o1 = new Object();
Object out = System.out;
//Works as System.out.println(Object) is defined
Method ms = out.getClass().getMethod("println",o1.getClass());
Object o2 = new Integer(4);
//Does not work as System.out.println(Integer) is not defined
Method mo = out.getClass().getMethod("println",o2.getClass());
我想知道是否有一种“简单”的方法来获得正确的方法,如果可能的话,最适合参数类型,或者我必须自己实现。
最贴合的是:
Object o1 = new Integer(1);
Object o2 = new String("");
getMethod(name, o1.getClass())//println(Object)
getMethod(name, o2.getClass())//println(String)
更新
澄清我需要的东西:
脚本引擎是我在空闲时间写的一个小项目,因此我没有必须遵循的严格规则。因此我认为选择从Engine调用的方法与java编译器在编译时仅使用动态类型而不是Object的静态类型选择方法的方式相同。(有或没有自动装箱)
这是我首先希望Class.getMethod()解决的问题。但是Class.getMethod()需要与Method声明的参数类型完全相同的类,使用子类将导致没有这样的方法Exception。这可能是有充分理由发生的,但是这个方法对我来说没用,因为我事先并不知道哪种参数类型适合。
另一种方法是调用Class.getMethods()并遍历返回的数组并尝试查找拟合方法。然而,如果我不想采用我遇到的第一个“好”方法,那将会很复杂,所以我希望现有的解决方案至少可以处理:
支持自动装箱也很不错
如果无法解析调用,则可能抛出异常(ma(String,Object),ma(Object,String),args = String,String)
(如果你在这里做到了,感谢花时间阅读它: - ))
答案 0 :(得分:2)
我建议您使用getMethods()
。它返回所有公共方法的数组(Method[]
)。
这里最重要的是:
“如果类声明了多个具有相同参数类型的公共成员方法,则它们都包含在返回的数组中。”
您需要做的是使用此数组中的结果来确定哪一个(如果有的话)是最接近的匹配项。由于最接近的匹配应该在很大程度上取决于您的要求和具体应用,因此自行编码是有意义的。
示例代码说明了如何执行此操作的一种方法:
public Method getMethod(String methodName, Class<?> clasz)
{
try
{
Method[] methods = clasz.getMethods();
for (Method method : methods)
{
if (methodName.equals(method.getName()))
{
Class<?>[] params = method.getParameterTypes();
if (params.length == 1)
{
Class<?> param = params[0];
if ((param == int.class) || (param == float.class) || (param == float.class))
{
//method.invoke(object, value);
return method;
}
else if (param.isAssignableFrom(Number.class))
{
return method;
}
//else if (...)
//{
// ...
//}
}
}
}
}
catch (Exception e)
{
//some handling
}
return null;
}
在此示例中,getMethod(String, Class<?>)
方法将返回仅包含一个int
,float
,double
或超类{{}的参数的方法1}}。
这是一个基本的实现 - 它返回适合该法案的第一种方法。您需要扩展它以创建匹配的所有方法的列表,然后根据某种标准对它们进行排序,并返回最佳匹配方法。
然后,您可以通过创建更通用的Number
方法来进一步处理它,以处理更多可能的“近似匹配”方案,甚至可能包含多个参数
HTH
编辑:正如@finnw指出的那样,使用Class#isAssignableFrom(Class<?> cls)
时要小心,因为它有其局限性,就像我在示例代码中一样,单独测试getMethod(String, Class<?>)
对象的原语。
答案 1 :(得分:2)
答案 2 :(得分:1)
AFAIK,没有简单的方法来做这种事情。当然,标准Java类库中没有任何内容可以做到这一点。
问题在于没有单一的“正确”答案。您需要考虑所有用例,确定“正确的方法”应该是什么,并相应地实现您的反射代码。