我想用
Class.getMethod(String name, Class... parameterTypes)
Run Code Online (Sandbox Code Playgroud)
找到我需要使用给定参数调用的方法,但显然如Bug 6176992中所述,Java不包括那里的自动装箱.因此,如果我的反射类有一个带有(String,int)签名的方法,你仍然会得到一个带有{String.class,Integer.class}数组作为参数的NoSuchMethodException.
这有什么解决方法吗?我能想到的唯一方法是调用getMethod()来处理原始和非原始类型的每个排列,我并不是真的想做.
编辑:为了使它更清楚:我很清楚原始类型类,但我不知道它们如何帮助解决我的问题.我的parameterTypes数组来自某个地方,我知道它只会返回非原始类型.我不能假设接口只会用原始类型声明,这正是我的问题:
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);
Run Code Online (Sandbox Code Playgroud)
PSp*_*eed 11
正如@Stephen C所提到的,你唯一的希望就是亲自进行搜索.他所有的警告都有,但我认为只要呼叫者知道警告,稍微有点灵活就可以覆盖大部分陷阱......而不是让你的来电者总是特别痛苦.
对于实际执行此类操作的代码,您可以在此处查看:http: //meta-jb.svn.sourceforge.net/viewvc/meta-jb/trunk/dev/src/main/java/org/progeeks/util/MethodIndex的.java?修订= 3811&视图=标记
findMethod()调用是入口点,但它委托(在一些缓存之后等)此方法:
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;
}
Run Code Online (Sandbox Code Playgroud)
InspectionUtils.areTypesCompatible()接受两个类型列表,规范化它们的基元,然后验证一个是"可分配"到另一个.因此,它将处理你有一个Integer的情况,并试图调用一个接受int的方法,以及你有一个String的情况,并试图调用一个接受Object的方法.它并不能处理具有一个int并调用需要浮动的方法的情况下.必须有一些特异性.
需要注意的是,上述方法只是按方法顺序搜索,因此如果存在歧义,则选择是任意的.到目前为止,我从未遇到过现实世界的问题.
以下是参考的兼容性检查:public static boolean areTypesCompatible(Class [] targets,Class [] sources){if(targets.length!= sources.length)return 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 );
}
Run Code Online (Sandbox Code Playgroud)
代码是BSD和我的,所以这些代码段是合法使用的.如果您决定直接使用此util包,则最新的公开发布版本位于:https: //meta-jb.svn.sourceforge.net/svnroot/meta-jb/trunk/dev/m2-repo/org/元JB /元JB-UTIL/0.17.1 /
我只提到这一点,因为很长一段时间没有捆绑下载,因为我的大多数活跃用户都是maven用户.我似乎更喜欢编写代码而不是削减完整版本.;)