Вызов метода с использованием отражения/преобразования списка в Var Args

У меня есть список параметров и имя метода. Я хочу вызвать метод, используя отражение. Когда я проверил документ Java для Method.invoke, это похоже на Method.invoke(object o, Object args...) . Я знаю, что передать для первого параметра (т. е. экземпляр, для которого следует вызывать метод, если его метод экземпляра), а args — это параметры для метода.

Но теперь у меня есть список, содержащий значения, которые нужно передать методу.

Скажем, например: я хочу вызвать метод ClassName.methodName(String , int, int) и у меня есть список, который содержит {val1, 3, 4}.

При использовании отражения это может быть похоже на Method.invoke(classNameInstance, ??????). Но я не уверен, как преобразовать список аргументов в varargs и передать.

Одним из способов может быть: если я знаю, что размер списка равен 3, я могу написать Method.invoke (classNameInstance, list.get(0), list.get(1), list.get(2)).

Но некоторые из методов, которые я хочу динамически вызывать, принимают от 0 до 12 аргументов. Таким образом, не выглядит «хорошо» создавать случай переключения и писать 12 случаев. Каждый будет проверять количество параметров и строить отдельный вызов с параметрами.

Любой способ сделать это, кроме как с помощью переключателя?

Любая помощь будет оценена.


person java_enthu    schedule 16.06.2011    source источник


Ответы (3)


Notation Object... означает не что иное, как Object[]. Это просто синтаксический сахар для Arraynotation. Передайте массив, и он будет работать.

person BaSche    schedule 16.06.2011
comment
Так что спасибо method.invoke(classNameInstance, argumentsList.toArray()); буду работать .... - person java_enthu; 16.06.2011
comment
На самом деле, я пробовал с этим, это отлично работает, если список одного простого типа. Но скажем, когда API (String, int, int) и List‹Serializable›: {val1, 2,3}. После преобразования их в массив его проблемы с выдачей, поскольку типы не совпадают. Средства Прежде чем я смогу напрямую передать их в метод вызова, мне нужно привести их к конкретному типу, который соответствует методу. Если это так, я не могу напрямую преобразовать в массив и использовать. Поправьте меня, если я ошибаюсь. - person java_enthu; 16.06.2011

ОТРЕДАКТИРОВАНО: это более общий подход, который работает для любого типа параметров vararg:

        Class<?> c = int.class;
        Object array = Array.newInstance(c, list.size());
        for (int i = 0; i < list.size(); i++)
                Array.set(array, i, list.get(i));
        Test.class.getDeclaredMethod("test", array.getClass()).invoke(
                new Test(), new Object[] { array });

void m(X...p) имеет ту же подпись, что и void m(X[] p). Вы не можете объявить оба в одном классе.

Вот как вызывать их с помощью отражения (примитивы и не-примитивы):

import java.util.*;
import java.lang.reflect.*;

class Test
{
        public static void main(String[] args) throws Exception
        {
                List<Integer> list = new ArrayList<Integer>();
                list.add(1); list.add(2); list.add(3);
                Test.class.getDeclaredMethod("test", Integer[].class).invoke(
                    new Test(), new Object[] { list.toArray(new Integer[0]) });
                int[] params = new int[list.size()];
                for (int i = 0; i < params.length; i++) params[i] = list.get(i);
                Test.class.getDeclaredMethod("test", int[].class).invoke(
                    new Test(), new Object[] { params });
        }

        public void test(int ... i) { System.out.println("int[]: " + i[0] + ", " + i[1] + ", " + i[2]); }
        public void test(Integer... i) { System.out.println("Integer[]" + Arrays.asList(i)); }
}
person Nick    schedule 16.06.2011
comment
Спасибо, но это будет для int, но этот список проблем приведения типа List‹Serializable› появится и будет сгенерировано несоответствие типов. - person java_enthu; 16.06.2011
comment
Добавлен пример с любым типом vararg -- Class‹?› c = int.class или что угодно. - person Nick; 16.06.2011

Varargs на самом деле просто массив.

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

Method method = MyClass.class.getMethod("someMethod", int[].class);
method.invoke(myInstance, argumentsList.toArray());
person Bohemian♦    schedule 16.06.2011
comment
List.toArray() вернет Object[] - не будет работать с int... - person Nick; 16.06.2011