Ошибка IllegalArgumentException: wrong number of arguments

190
10 января 2018, 18:08

Суть работы: есть пакет, в котором генерируется массив чисел и еще один пакет, в котором происходит сортировка массива. Нужно реализовать модуль, который автоматически будет находит массив из пакета(по аннотации @Filler) и сортировать его, прогоняя этот массив через класс, в котором происходит сортировка (этот класс унаследован от класса Sort) пробую реализовать этот самый "модуль":

public class Analyzer{
    public static void runAllAnnotatedMethods() throws Exception {
         Class<?> c = Class.forName("fillers.ArrayFiller");
         Method[] m = c.getDeclaredMethods();
        for (Method method : m) {
            if (method.isAnnotationPresent(Filler.class)) {
                ArrayFiller a = (ArrayFiller) method.invoke(new ArrayFiller[]{});//static method
                Set<Class<? extends Sort>> subTypesOf = (new Reflections("sorters")).getSubTypesOf(Sort.class);
                for (Class c1 : subTypesOf){
                    Method[] m1 = c1.getDeclaredMethods();
                    for (Method method1 : m1) {
                        if (a != null) {
                            method1.invoke(a, new ArrayFiller[]{});//non static method
                        }
                    }
                }

выдает ошибку:

Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at analyzer.Analyzer.runAllAnnotatedMethods(Analyzer.java:21)
    at Main.main(Main.java:7)

что не правильно я делаю?

вот класс fillers.ArrayFiller и аннотированный метод:

public class ArrayFiller {
    @Filler
    public static void randomized(int[]a) {
        a = new int[10000];
        for (int i = 0; i < a.length; i++) {
            a[i] = (int) Math.round(Math.random() * 100);
        }
    }
Answer 1

Вы не отметили строку, на которой возникает ошибка (Analyzer.java:21), полагаю что это вызов randomized:

ArrayFiller a = (ArrayFiller) method.invoke(new ArrayFiller[]{});

Вижу как минимум две проблемы. Скорее всего действительно придется пересмотреть процесс:

  1. Method.invoke принимает два аргумента:

    • obj — объект от которого выполняется метод, для статических методов игнорируется;
    • args — аргументы, которые нужно передать в метод.

    Соответственно, строка:

    ArrayFiller a = (ArrayFiller) method.invoke(new ArrayFiller[]{})
    

    для статического метода проигнорирует переданный пустой массив, попытается выполнить метод без аргументов, и будет ожидать ArrayFiller в качестве результата. Так можно выполнить метод с сигнатурой:

    static ArrayFiller createArrayFiller();
    

    в то время как randomized принимает аргумент и ничего не возвращает. Ошибка говорит о несоответствии аргументов.

  2. Метод randomized ничего не делает.

    В randomized создается новый объект, который присваевается переменной-аргументу функции. Соответственно, переданный в метод объект (если он был передан) не изменится.

    Это можно проверить без рефлексии, выполнив такого кода:

    int[] a = new int[1];
    ArrayFiller.randomize(a);
    System.out.println(a.length); //1
    

    объект на который ссылается переменная a никак не изменился.

    Рекомендую тщательно отладить поведение методов в ArrayFiller прежде чем приниматься за их автоматизацию.

Исправление:

Для начала понадобится возвращать значение из randomized. Метод никак не использует аргумент, его можно убрать:

@Filler
public static int[] randomized() {
    int[] a = new int[10000];
    //... здесь заполнение
    return a;
}

такой метод можно вызвать при помощи рефлексии, не передавая аргументов:

int[] array = (int[]) method.invoke(null);

Что там дальше с сортировкой не ясно, предлагаю выправить заполнить и если после этого возникнут вопросы, то разбираться с ними отдельно.

Answer 2

Так, смотрите:

Method[] m = c.getDeclaredMethods();

Вы находите все методы, в принципе ничего сложного. Дальше вы вызываете все методы в цикле, но т.к. в ArrayFiller всего 1 метод, то вызывается соответственно только он, public static void randomized(int[]a). Тут тоже всё понятно.

Поехали дальше. В следующей строке вы пытаетесь вызвать статичный метод.

ArrayFiller a = (ArrayFiller) method.invoke(new ArrayFiller[]{});

Чтобы вызывать статичный метод, метод invoke первым аргументом должен принимать null, а вторым массив int[] a. У вас же передается новый объект и не передается массив, т.е.:

method.invoke(null, new int[]{});

Но у вас же метод randomized определен как void, т.е. не возвращает значения, а передавать какой-либо массив int[] бесполезно, ведь он заново инициализируется:

public static void randomized(int[]a) {
        a = new int[10000];

Я не до конца понял, что делает этот участок кода:

Set<Class<? extends Sort>> subTypesOf = (new Reflections("sorters")).getSubTypesOf(Sort.class);
    for (Class c1 : subTypesOf){
    Method[] m1 = c1.getDeclaredMethods();
    for (Method method1 : m1) {
        if (a != null) {
            method1.invoke(a, new ArrayFiller[]{});//non static method
        }
    }
}

Но в целом вы ведь получаете список каких-то классов, которые наследуются в ArrayFiller, ведь вы пытаетесь вызвать методы классов subTypesOf на экземпляр ArrayFiller:

method1.invoke(a, new ArrayFiller[]{});

В общем не понятно, что должно быть в итоге и что представляет из себя ArrayFiller, для чего он.

READ ALSO
Android анимация расходящихся кругов

Android анимация расходящихся кругов

Вообщем у меня есть кнопка круглая выглядит вот так:

160
SIP сервер формирование ответов

SIP сервер формирование ответов

Есть sip-сервер, написанный на java, он работает, но через раз, проблема в формировании ответных сообщений от сервераКак я понимаю, то мне приходит...

157
Переход от окна редактирования в окно run IDEintellij-idea

Переход от окна редактирования в окно run IDEintellij-idea

Добрый день, подскажите какими сочетаниями клавиш в intellij-idea можно перейти из окна редактирования в окно run для ввода данных с клавиатурыОбратно...

134
Junit import error при запуске тестов

Junit import error при запуске тестов

Подключил все необходимое,но при запуске теста - еррорКакой-то трабл с подключением Junit

210