[Solved] Java Call Error: java.lang.IllegalArgumentException: wrong number of arguments

Problem description

Class target. Java has an execute method, which takes a string array as a parameter

public class Target {
    public void execute(String[] args) {
        System.out.println("call execute method with parameter type String[]");
    }
}

Call this method through reflection in the following way

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        String[] parameters = {"1"}; // parameter array
        Class targetClass = Class.forName("Target");// get target class "Target"
        Object instance= targetClass.newInstance();
        Method execute = targetClass.getDeclaredMethod("execute", String[].class);// get target method "execute"
        execute.invoke(instance, parameters);// invoke method
    }
}

As a result, the console reports an error

Exception in thread “main” java.lang.IllegalArgumentException: wrong number of arguments 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:498) at Test.main(Test.java:16)

Problem Analysis

Find the Method.invoke method, which actually receives a variable-length parameter (Varargs).

public Object invoke(Object obj, Object... args)

When the compiler finds something like

method.invoke(object, arg1, arg2)

In such a representation, an array is implicitly created, similar to new object [] {arg1, arg2}, and then is used as the parameter of the invoke method. But if the parameter of the target method is an array, such as

method.invoke(object, Object[])

The compiler will think that you have put all the parameters in the array, so it won’t wrap them again. In this case, the elements in the array , not the array itself, are passed to the target method as parameters

So let’s look back and forth at the above example. In fact, the main method finally attempts to call the execute method with a string type as a parameter through reflection. Let’s do an experiment

public class Target {
    public void execute(String[] args) {
        System.out.println("call execute method with parameter type String[]");
    }

    public void execute(String arg) {
        System.out.println("call execute method with parameter type String");
    }
}

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        String[] parameters = {"1"}; // parameter array
        Class targetClass = Class.forName("Target");// get target class "Target"
        Object instance= targetClass.newInstance();
        Method execute = targetClass.getDeclaredMethod("execute", String.class);// get target method "execute"
        execute.invoke(instance, parameters);// invoke method
    }
}

The final print is (note that the two method parameters are different)

call execute method with parameter type String

Problem solving

In fact, the solution to this situation is very simple, as long as package the array as the first element of the object array , then the compiler will pass the array itself as a parameter to the target method, as follows:

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        String[] parameters = {"1"}; // parameter array
        Class targetClass = Class.forName("Target");// get target class "Target"
        Object instance = targetClass.newInstance();
        Method execute = targetClass.getDeclaredMethod("execute", String[].class);// get target method "execute"
        execute.invoke(instance, new Object[] {parameters});// invoke method
    }
}

Summary

When using reflection to call a method, if the input parameter of the target method is an array, the array should be wrapped in another object array

Similar Posts: