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??