简体   繁体   中英

What can I pass as the second argument to java reflection's getMethod to signify no parameter(s)?

I'm doing some weird reflection stuff to get around wrapping a whole bunch of methods in a class. The java docs suggest that null would be the solution, but it fails with NoSuchMethodException.

 public Method getMethod(String name,
                         Class[] parameterTypes)
                  throws NoSuchMethodException,
                         SecurityException

If parameterTypes is null, it is treated as if it were an empty array.

To begin with I'm trying:

private <T> T invokeWrappedFunction(Object instance, String methodName, Object... args) {
    try{
        Method m = instance.getClass().getMethod(methodName, (args == null ? null : args.getClass()));
        return (T) m.invoke(instance, args);
    } catch(Exception e) {
        //This is an example, you're lucky I even acknowledged the exception!
    }
}

Now eventually there will be lots of extra functionality in there and instance isn't an unknown type so I can do helpful stuff on failures and such. The real question is how do I get the getMethod working?

I think you pass a new Class[0];

eg

final static Class[] NO_ARGS = new Class[0];
Method m = Method m = instance.getClass().getMethod(methodName, NO_ARGS);

ADDED

Maybe I'm not understanding the complete question. If the problem is not the no-args version. but the with args version, you can handle it if the args are an array of all the same type . If they are different types I think you are in trouble.

First, verify that args is not null and that it is an array, then call Class.getComponentType(), eg

if (args != null) {
   Class c = args.getClass();
   if (c.isArray()) 
      Class arrayClass = c.getComponentType();
   // do something here...
}

Based on the comments I'm adding an answer to illustrate what I mean.

private <T> T invokeWrappedFunction(Object instance, String methodName, Object... args) {
    Class[] classes = null;
    if (args != null) {
        classes = new Class[args.length];
        for (int i = 0; i < args.length; ++i) {
            classes[i] = args[i].getClass();
        }
    }

    try {
        Method m = instance.getClass().getMethod(methodName, classes);
        return (T) m.invoke(instance, args);
    } catch(Exception e) {
        //This is an example, you're lucky I even acknowledged the exception!
    }
}

This still will not work in some cases, though. If the object you're passing in is a subclass of the formal parameter type it will not work.

For example:

interface I {
    void method();
}
class C implements I {
    public void method() {
        ... code ...
    }
}

If you try to reflect a method expecting to take an I but you pass it a C then getMethod(...) will throw an exception instead of returning the method you want because C is not equal to I .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM