Class.getMethod()反射和自动装箱的任何解决方案? [英] Any solution for Class.getMethod() reflection and autoboxing?

查看:103
本文介绍了Class.getMethod()反射和自动装箱的任何解决方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用

Class.getMethod(String name, Class... parameterTypes)

找到我需要用给定参数调用的方法,但显然如错误6176992 Java不包括那里的自动装箱。因此,如果我的反射类有一个带有(String,int)签名的方法,你仍然会得到一个带有{String.class,Integer.class}数组作为参数的NoSuchMethodException。

to find the method I need to invoke with the given parameters, but apparently as described in Bug 6176992 Java doesn't include autoboxing there. So if my reflected class has a method with a (String, int) signature you still get a NoSuchMethodException with a {String.class, Integer.class} array as a paremeter.

这有解决方法吗?我可以想到的唯一方法是调用getMethod()以及我不想要的原始和非原始类型的每个排列。

Is there any sollution for this? The only way I could think of to call getMethod() with every permutation of primitive and non primitive types which I don't really want to do.

编辑:制作它更清楚:我很清楚原始类型类,但我不知道它们如何帮助解决我的问题。我的parameterTypes数组来自某个地方,我知道它只返回非原始类型。我不能假设接口只会用原始类型声明,这正是我的问题:

To make it more clear: I am well aware of the primitive type classes, but I don't see how they could help to solve my problem. My parameterTypes array comes from somewhere and I know that it will only return non primitive types. I can not assume that the interface will only be declared with primitive types and that's exactly my problem:

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所提到的,你唯一的希望是自己做搜索。他的所有注意事项都有,但我认为只要呼叫者知道警告就会有一点灵活性来覆盖大部分陷阱......而不是让你的来电者总是特别痛苦。

As @Stephen C mentions, your only hope is to do the search yourself. All of his caveats hold but I'd argue a little flexibility would go a long way to covering most of the gotchas as long as the callers were aware of the caveats... versus making your callers always be painfully specific.

对于实际执行此类操作的代码,您可以在此处查看:
http://meta-jb.svn.sourceforge.net /viewvc/meta-jb/trunk/dev/src/main/java/org/progeeks/util/MethodIndex.java?revision=3811&view=markup

For code that actually does something like this you can look here: http://meta-jb.svn.sourceforge.net/viewvc/meta-jb/trunk/dev/src/main/java/org/progeeks/util/MethodIndex.java?revision=3811&view=markup

findMethod()调用是入口点,但它委托(在一些缓存之后等)此方法:

The findMethod() call is the entry point but it delegates (after some caching, etc.) to this method:

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并调用浮点数的方法的情况。必须有一些特异性。

InspectionUtils.areTypesCompatible() takes two lists of types, normalizes their primitives, and then verifies that one is "assignable" to the other. So it will handle the case where you have an Integer and are trying to call a method that takes int as well as the case where you have a String and are trying to call a method that takes Object. It does not handle the case of having an int and calling a method that takes float. There has to be some specificity.

一点需要注意的是,上述方法只是按方法顺序搜索,所以如果有歧义那么选择是任意的。到目前为止,我从未遇到过现实世界的问题。

The one caveat is that the above method just searches in method order so if there are ambiguities then the selection is arbitrary. I've never encountered a real-world issue, so far in practice.

以下是参考的兼容性检查:
public static boolean areTypesCompatible(Class [ ]目标,类[]来源){
if(targets.length!= sources.length)
返回false;

Here is the compatibility check for reference: 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 );
}

代码是BSD和我的,所以这些代码段是合法使用的。如果您决定直接使用此util包,则最新的公开发布版本位于:
https://meta-jb.svn.sourceforge.net/svnroot/meta-jb/ trunk / dev / m2-repo / org / meta-jb / meta-jb-util / 0.17.1 /

The code is BSD and mine so the snippets are legal to use. If you decide you'd rather use this util package directly the most recent public release is here: https://meta-jb.svn.sourceforge.net/svnroot/meta-jb/trunk/dev/m2-repo/org/meta-jb/meta-jb-util/0.17.1/

我只提到那个因为那里由于我的大部分活跃用户都是maven用户,因此很长一段时间没有捆绑下载。我似乎更喜欢编写代码而不是剪切完整版本。 ;)

And I only mention that because there hasn't been a bundled download in a long time since most of my active users are maven users. I seem to be more fond of writing code than cutting full releases. ;)

这篇关于Class.getMethod()反射和自动装箱的任何解决方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆