我想用

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用户。我似乎比编写完整版本更喜欢编写代码。 ;)

10-07 18:56