Ошибка неверного числа аргументов при вызове метода - PullRequest
23 голосов
/ 19 ноября 2011

У меня есть класс AClass и метод someMethod, который получает массив Object в качестве параметра.

public class AClass {
    public void someMethod(Object[] parameters) {
    }
}

В основном, когда я пытаюсь вызвать этот метод для объекта, который я создал, и дать массив объектов в качестве параметра для этого метода

Object[] parameters; // lets say this object array is null
Class class = Class.forName("AClass");
Object anObject = class.newInstance();

Method someMethod = class.getDeclaredMethod("someMethod", parameters.getClass());
someMethod.invoke(anObject, parameters);

Я получаю "неправильное количество аргументов". Что мне не хватает?

Ответы [ 5 ]

23 голосов
/ 19 ноября 2011

Все будет в порядке.

    Object[] parameters ={new Object()}; // lets say this object array is null
    Class clas = Class.forName("AClass");
    Object anObject = clas.newInstance();

    Object[] param ={parameters};

    Method someMethod = clas.getDeclaredMethod("someMethod", parameters.getClass());
    someMethod.invoke(anObject, param);

Будьте осторожны со вторым параметром метода invoke.Это сам Object [], и тип аргумента вашего метода тоже Object [].

10 голосов
/ 19 ноября 2011

Чтобы немного рассказать о том, что говорят Орион и Бяобяоци. , .

Что вас, вероятно, смущает, так это то, что Method.invoke(Object, Object...) обычно может просто принимать аргументы, так сказать; когда компилятор видит что-то вроде someMethod.invoke(someObject, arg1, arg2), он неявно создает массив new Object[]{arg1, arg2} и затем передает этот массив в Method.invoke. Method.invoke затем передает элементы этого массива в качестве аргументов вызываемому методу. Пока все хорошо.

Но когда компилятор видит что-то вроде someMethod.invoke(someObject, someArray), он предполагает, что вы уже упаковали аргументы в массив; поэтому он не будет переупаковывать их снова. Тогда Method.invoke будет пытаться передать элементы из someArray в качестве аргументов вызываемому методу, вместо передачи someArray самой в качестве аргумента.

(Это всегда, как работает нотация ...; она принимает либо массив, содержащий элементы соответствующего типа, или ноль или более аргументов соответствующего типа.)

Итак, как сказали Ори и Бяобяоци, вам нужно перевернуть ваш parameters в дополнительный массив new Object[] {parameters}, чтобы сам по себе parameters передавался в ваш метод.

Имеет ли это смысл?

9 голосов
/ 19 ноября 2011

Метод Method.invoke принимает объект для получения вызова метода и массив аргументов метода. Поскольку ваш метод принимает один аргумент, указанный массив должен иметь размер один.

попробуйте создать новый массив размером 1:

someMethod.invoke(anObject, new Object[] {parameters});

Обратите внимание, что одно значение в этом массиве может быть нулевым. Это будет имитировать anObject.someMethod(null)

4 голосов
/ 19 ноября 2011

Параметры для invoke - это массив Object; ваши параметры должны быть Object[] , содержащим Object[], который вы передаете someMethod.

Вам не нужно создавать непосредственный массив для этого, поскольку подпись invoke равна invoke(Object, Object...), но в вашем случае вы пытаетесь передать массив пустой . Если вы хотите передать значение null:

Object[] parameters = { null };
...
someMethod.invoke(anObject, parameters);

В конечном счете, однако, другие ответы верны: вам нужно передать Object[], содержащий запись для каждого из параметров метода .

1 голос
/ 19 ноября 2011

попробуйте это:

    someMethod.invoke(anObject, new .java.lang.Object[1][]{parameters});

Я получил автоматическое создание версии кода Reflection API с помощью dp4j:

$ javac -cp dp4j-1.2-jar-with-dependencies.jar -Averbose=true AClass.java
AClass.java:10: Note: 
import com.dp4j.*;

public class AClass {

    public AClass() {
        super();
    }

    public void someMethod(Object[] parameters) {
    }

    @Reflect(all = true)
    public static void main(String... args) throws ... {
        Object[] parameters = null;
        ...
        AClass anObject;
        anObject = (.AClass)aClassConstructor.newInstance();
        java.lang.reflect.Method someMethodWithArrayMethod = null;
        someMethodWithArrayMethod = Class.forName("AClass").getDeclaredMethod("someMethod", .java.lang.Object[].class);
        someMethodWithArrayMethod.setAccessible(true);
        someMethodWithArrayMethod.invoke(anObject, new .java.lang.Object[1][]{parameters});
    }
}
...