我想用
Class.getMethod(String name, Class... parameterTypes)
来查找需要使用给定参数调用的方法,但是显然像Bug 6176992中所述,Java不包括自动装箱。因此,如果我的反射类有一个带有(String,int)签名的方法,您仍然会收到一个NoSuchMethodException,它带有一个{String.class,Integer.class}数组作为参数。
有什么解决办法吗?我想到的唯一方法是,对每个我真的不想做的基本类型和非基本类型的每个排列调用getMethod()。
编辑:更明确地说:我很清楚原始类型类,但是我看不到它们如何帮助解决我的问题。我的parameterTypes数组来自某个地方,我知道它只会返回非原始类型。我不能假设只用原始类型声明接口(interface),而这正是我的问题:
public interface TestInterface()
{
public void doTest(Integer i1, int i2, double d3, Double d);
}
Class<?>[] classes = { Integer.class, Integer.class, Double.class, Double.class }
// Due to autoboxing I should become the doTest method here, but it doesn't work
TestInterface.class.getMethod("doTest", classes);
最佳答案
正如@Stephen C提到的那样,您唯一的希望就是自己进行搜索。他所有的警告都成立了,但我认为只要 call 者知道这些警告,稍微灵活一点就能覆盖大多数陷阱……而不是让您的 call 者总是非常痛苦。
对于实际上执行以下操作的代码,您可以在这里查看:
http://meta-jb.svn.sourceforge.net/viewvc/meta-jb/trunk/dev/src/main/java/org/progeeks/util/MethodIndex.java?revision=3811&view=markup
findMethod()调用是入口点,但它(在进行某些缓存后)委托(delegate)给此方法:
private Method searchForMethod( String name, Class[] parms ) {
Method[] methods = type.getMethods();
for( int i = 0; i < methods.length; i++ ) {
// Has to be named the same of course.
if( !methods[i].getName().equals( name ) )
continue;
Class[] types = methods[i].getParameterTypes();
// Does it have the same number of arguments that we're looking for.
if( types.length != parms.length )
continue;
// Check for type compatibility
if( InspectionUtils.areTypesCompatible( types, parms ) )
return methods[i];
}
return null;
}
InspectionUtils.areTypesCompatible()接受两个类型的列表,对它们的基元进行规范化,然后验证一个对其他类型是“可分配的”。因此,它将处理您拥有Integer并尝试调用采用int的方法的情况,以及您拥有String并尝试调用采用Object的方法的情况。它不处理具有int并调用采用float的方法的情况。必须有一些特殊性。
一个警告是,上述方法只是按方法顺序搜索,因此,如果存在歧义,则选择是任意的。到目前为止,我从未遇到过现实世界中的问题。
这是兼容性检查,以供引用:
public static boolean areTypesCompatible(Class [] target,Class [] sources){
if(targets.length!= sources.length)
返回false;
for( int i = 0; i < targets.length; i++ ) {
if( sources[i] == null )
continue;
if( !translateFromPrimitive( targets[i] ).isAssignableFrom( sources[i] ) )
return false;
}
return( true );
}
代码是BSD和我的代码,因此这些代码段合法使用。如果您决定直接使用此util软件包,则最新的公共(public)发行版本在这里:
https://meta-jb.svn.sourceforge.net/svnroot/meta-jb/trunk/dev/m2-repo/org/meta-jb/meta-jb-util/0.17.1/
我只提到那是因为很长一段时间以来没有 bundle 下载,因为我的大多数 Activity 用户都是maven用户。我似乎比编写完整版本更喜欢编写代码。 ;)