7

I must miss something very fundamental. When I try to pass an array of any kind during a method invocation I get an error. However when I do it normally it works.

This is the complete code that fails

import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws Exception {

        // Normal
        MyClass.sayHello(new String[] {"StackOverflow"});

        // Reflection
        Method m = MyClass.class.getMethod("sayHello", String[].class);
        m.invoke(null, new String[]{"StackOverflow"});
    }

    static class MyClass {
        public static void sayHello(String[] args) {
            System.out.println("Hello " + args[0]);
        }
    }
}

The Exception thrown

Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
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:497)
at Main.main(Main.java:11)

String... does not work either btw.

1 Answer 1

7

The problem is that the second parameter to invoke is meant to be an array of arguments - you're only specifying a single argument.

In most cases that would be okay as the second parameter of Method.invoke is a varargs parameter, but as your argument is already an array compatible with Object[], the compiler isn't creating a wrapper array. I'd expect you to get a compile-time warning like this:

Main.java:11: warning: non-varargs call of varargs method with inexact argument type for
                       last parameter;
        m.invoke(null, new String[]{"StackOverflow"});
                       ^
  cast to Object for a varargs call
  cast to Object[] for a non-varargs call and to suppress this warning

You could either explicitly create an array wrapping the argument, or cast the argument to Object so that the compiler needs to wrap it itself:

// Creates the wrapper array explicitly
m.invoke(null, new Object[] { new String[] { "StackOverflow" } });

or

// Compiler creates the wrapper array because the argument type is just Object
m.invoke(null, (Object) new String[] { "StackOverflow" });
Sign up to request clarification or add additional context in comments.

3 Comments

Yes, I got the same warning. It doesn't make any sense why Java would need an array of array arguments, but it works. Thanks!
@TomTom: It makes perfect sense: it needs an array because there can be multiple arguments. The only element of that array is itself an array, because the parameter to the method is an array. Try adding another parameter to the method and it'll make more sense. And in future, never ignore warnings :)
@JonSkeet It just made click. It expects a String[] as an argument, while also needing an Array as an argument for the arguments. Thanks, I won't! I'm just new to varargs :)

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.