How to call method which takes an array using reflection

arrays, java

Solution

Some general info

The `Method#invoke` has two parameters

- `Object obj` which takes object on which method should be invoked

- `Object... args` which takes Object[] array holding all arguments for method.

So if we want to call method like `methodName(foo, bar, baz)` the `Object... args` should end up becoming `new Object[]{foo, bar, baz}`.

Similarly since `useArray` expects one argument which is `String[]` array itself, the `Object... args` should end up wrapping that array and becoming `new Object[]{ new String[]{"Hi"} }`

Solution

We can achieve that via explicitly writing

m.invoke(new A(), new Object[]{ new String[]{ "Hi" } });
//                ^^^^^^^^^^^^^----------------------^

OR

by telling compiler to treat `String[]` as single `Object` to let varargs wrap it inside `new Object[]{...}` array for us. We can achieve that by casting

m.invoke(new A(), (Object) new String[]{"Hi"});
//                ^^^^^^^^

Problem with your code

The `String[]` array is subtype of `Object[]`. This means that it ends up being assigned as value of `args` like

Object... args = new String[]{"Hi"};

instead of being wrapped by Object[] array like

Object... args = new Object[]{ new String[]{"Hi"} };

Because of that you end up with code representing `new A().useArray("Hi")`.

But since `useArray` method expects `String[]` array and not `String` you are getting `java.lang.IllegalArgumentException: argument type mismatch` exception.

Problem

Consider the following complete Java program. ``` public class Reflection { static class A { public void useArray( String[] args ) { System.out.println( "Args are " + Arrays.toString( args ) ); } } public static void main( String[] args ) throws Exception { Method m = A.class.getMethod( "useArray", String[].class ); m.invoke( new A(), new String[] { "Hi" } ); } } ``` Trying to run this, you get an error: ``` Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch ``` If instead of using only one String in the array passed to `invoke` you pass more than one, then you get: ``` Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments ``` So, clearly, because `invoke`'s signature is: ``` invoke(java.lang.Object obj, java.lang.Object... args) ``` when I call `invoke` using an array, the call is getting "translated" to: ``` m.invoke( new A(), "Hi" ); ``` How to make Java understand that I do want my array to be passed into `invoke` intact??

Original source