3

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

1 Answer 1

6

Some general info

The Method#invoke has two parameters

  1. Object obj which takes object on which method should be invoked
  2. 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.