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??
The Method#invoke has two parameters
Object obj which takes object on which method should be invokedObject... 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"} }
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"});
// ^^^^^^^^
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With