Simple question, how make this code working ?
public class T {
public static void main(String[] args) throws Exception {
new T().m();
}
public // as mentioned by Bozho
void foo(String... s) {
System.err.println(s[0]);
}
void m() throws Exception {
String[] a = new String[]{"hello", "kitty"};
System.err.println(a.getClass());
Method m = getClass().getMethod("foo", a.getClass());
m.invoke(this, (Object[]) a);
}
}
Output:
class [Ljava.lang.String;
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
works. The problem is that
getMethod(..)
only searches thepublic
methods. From the javadoc:Update: After successfully getting the method, you can invoke it using:
that is - create a new
Object
array with one element - theString
array. With your variable names it would look like://prior to edit:
Your problem is the fact that
getMethod
looks for apublic
member.From the
Class.getMethod
(emphasis mine):So you have two options:
public void foo(String... s)
and usegetMethod
getDeclaredMethod
insteadNote that the same difference exists for
getField/s
vsgetDeclaredField/s
andgetConstructor/s
vsgetDeclaredConstructor/s
.//
invoke
problemThis is particularly nasty, but what happens is that
invoke(Object obj, Object... args)
makes it tricky if you need to pass an array of reference type as an only argument, because it is cast-able toObject[]
, even though it should be wrapped inside anew Object[1]
instead.You can do:
This bypasses the vararg mechanism. More succinctly you can also do:
The cast to
Object
makes the vararg mechanism do the work of creating the array for you.The trick is also needed when passing a
null
as an argument to varargs, and has nothing to do with reflection.