I want to use getDeclaredMethod()
to find a method with this signature:
public void foo(String inArg1, Object... inArgs);
Using this call:
Class<?>[] argClasses = { String.class, Integer.class };
Method m = clazz.getDeclaredMethod("foo", argClasses);
But it generates a NoSuchMethodException
exception. However, it is possible to invoke the method (assuming you find it some other way):
Object[] args = { "arg1", new Integer(2) };
m.invoke(instance, args);
I could list them all, with getDeclaredMethods()
, and then try to do the signature matching myself, but that seems like a lot of work.
Should what I want to do be possible? Am I just missing something dumb?
The method is callable with any object(s) because it is declared to accept object(s). - But, because it is declared with Object
type you won't find via getDeclaredMethod()
if you don't search for the exact declared type.
You should be able, though, to iterate over all declared methods and check on their parameter types to see if they are assignable from your given type to find all methods which are callable with your parameters.
Example:
Class[] signature = {String.class, Integer.class};
Method[] methods = someClass.getDeclaredMethods();
for ( Method m : methods ) {
Class[] params = m.getParameterTypes();
if ( params.length == signature.length ) {
int i;
for ( i = 0; i < signature.length && params[i].isAssignableFrom( signature[i] ); i++ ) {
}
if ( i == signature.length ) {
System.out.println("Found matching method: " + m.getName());
}
}
}
However, I have not checked which type(s) Object...
actually is assignable from. I assume that it is not Integer
but rather Integer[]
since the varargs are compiled to arrays.
A vararg argument is just syntactic sugar for an array. The signature of the method is
foo(String, Object[]);
and not
foo(String, Integer);
The only legal way to find foo method is
Class<?>[] argClasses = { String.class, Object[].class };
Method m = clazz.getDeclaredMethod("foo", argClasses);
as for
Object[] args = { "arg1", new Integer(2) };
m.invoke(instance, args);
it's quite legal, just as calling foo without reflection
foo("str", new Integer(2));
You should treat varargs
as an array:
Class<?>[] argClasses = { String.class, Object[].class };
Method m = clazz.getDeclaredMethod("foo", argClasses);