chris chris - 2 months ago 21
Java Question

How to perform reflection call to a method carries String, String, String... as parameters?

I'm facing an issue where I need to use reflection call to invoke method which carries parameters String, String, String... . My code is as below

public void testArrayParams(String first, String second, String... strings) {

System.out.println("First: " + first);
System.out.println("Second: " + second);

System.out.println("Size of String... strings: " + strings.length);
for(int i = 0; i < strings.length; i ++) {
System.out.println(i + ": " + strings[i]);
}

}


And below is the main method

public static void main(String[] args) {
Dummy dummy = new Dummy();
//dummy.testArrayParams("Hello", "World", "This is ", "passed in ", "format String... strings.");

String[] params = {"Hello", "World", "This is ", "passed in ", "format String... strings."};
String method = "testArrayParams";

try {
Class<?> clazz = Class.forName("com.bt.testafix.utils.Dummy");
Method[] methods = clazz.getMethods();

for (Method m : methods) {
if (m.getName().equalsIgnoreCase(method)) {
//m.invoke(clazz, (Object[]) params);
m.invoke(clazz, new Object[]{params});
break;
}
}

} catch (ClassNotFoundException | IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


It throws below exception when I run the code

java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)


I have tried change to
m.invoke(clazz, (Object[]) params);
, which is a casting but still giving the same exception. Any idea I can resolve this issue?

Answer Source

If you look at the parameter information that Method instance gives you, you'll find that the last parameter is a String[] parameter, because varargs are implemented in Java as an array parameter.

So your params should reflect that:

Object[] params = {
    "Hello",
    "World",
    new String[] {
        "This is ",
        "passed in ",
        "format String... strings."
    }
};

Separately, two problems with your invoke call:

  1. The method isn't a method on clazz, you'll need an instance (since it's an instance method). E.g., clazz.newInstance() or similar.

  2. You've used new Object[]{params}, which means you're passing a single argument to the method. It expects three.

So:

m.invoke(clazz.newInstance(), params);

Working live copy