Суть работы: есть пакет, в котором генерируется массив чисел и еще один пакет, в котором происходит сортировка массива. Нужно реализовать модуль, который автоматически будет находит массив из пакета(по аннотации @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);
}
}
Вы не отметили строку, на которой возникает ошибка (Analyzer.java:21
), полагаю что это вызов randomized
:
ArrayFiller a = (ArrayFiller) method.invoke(new ArrayFiller[]{});
Вижу как минимум две проблемы. Скорее всего действительно придется пересмотреть процесс:
Method.invoke
принимает два аргумента:
obj
— объект от которого выполняется метод, для статических методов игнорируется;args
— аргументы, которые нужно передать в метод.Соответственно, строка:
ArrayFiller a = (ArrayFiller) method.invoke(new ArrayFiller[]{})
для статического метода проигнорирует переданный пустой массив, попытается выполнить метод без аргументов, и будет ожидать ArrayFiller
в качестве результата. Так можно выполнить метод с сигнатурой:
static ArrayFiller createArrayFiller();
в то время как randomized
принимает аргумент и ничего не возвращает. Ошибка говорит о несоответствии аргументов.
Метод 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);
Что там дальше с сортировкой не ясно, предлагаю выправить заполнить и если после этого возникнут вопросы, то разбираться с ними отдельно.
Так, смотрите:
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
, для чего он.
Есть sip-сервер, написанный на java, он работает, но через раз, проблема в формировании ответных сообщений от сервераКак я понимаю, то мне приходит...
Добрый день, подскажите какими сочетаниями клавиш в intellij-idea можно перейти из окна редактирования в окно run для ввода данных с клавиатурыОбратно...
Подключил все необходимое,но при запуске теста - еррорКакой-то трабл с подключением Junit