Отражение Java: getMethod(метод String, Object[]. Class) не работает

У меня есть следующий код:

public void myMethod(Object... args) {
    System.out.println("this is myMethod");
}

public void invokeMyMethod() {
    Method s = this.getClass().getMethod("myMethod", Object[].class);
    Object[] ex = new Object[2];
    ex[0] = "hi";
    ex[1] = "there";
    s.invoke(this, ex);
}

Я получаю исключение java.lang.IllegalArgumentException: неверное количество аргументов. В чем дело?

3 ответа

Решение

Вам нужно вызвать метод следующим образом:

s.invoke(this, new Object[]{new Object[]{"hi", "there"}});

(... или используйте альтернативу в ответе @Jon.)

Причина, по которой ваш текущий код дает сбой, заключается в том, как в Java реализованы различные методы. По существу, T1 xxx(T2... args) является синтаксическим сахаром для T1 xxx(T2[] args), И когда вы вызываете методы, xxx(arg1, arg2, arg3) является синтаксическим сахаром для xxx(new T2[]{arg1, arg2, arg3}),

В этом случае вы пытаетесь вызвать varadic метод, используя другой varadic метод с тем же базовым типом массива, и существует несколько возможных интерпретаций кода.

Когда возможны две интерпретации неконтролируемого вызова, Java предполагает, что вы пытаетесь использовать "неагрессивную" версию вызова вместо "подслащенной" версии. Или, если быть более точным, "подслащенная" интерпретация используется тогда и только тогда, когда:

  • количество фактических аргументов не равно количеству формальных параметров, или
  • последний фактический аргумент НЕ совместим по присваиванию с типом (массив) последнего формального параметра.

Если вам интересно, это поведение указано в JLS в разделе 15.12.4.2.

Итак... мое решение работает путем форсирования неварадикальной интерпретации и явного построения необходимого массива. Решение @ Джона работает путем принудительного правильного интерпретации.

Проблема здесь с переменными аргументами (Object...) тот Method.invoke принимает.

Изменение этой строки

 s.invoke(this, ex);

к этому

 s.invoke(this, (Object)ex);

буду работать.

На заднем фоне, Object... передается как Object[], Ява видит твои Object[] и решив не оборачивать это в другое Object[], Приведя к Objectтеперь он просто видит это и возвращается к своему обычному завершающему поведению - так же, как другие ответы делают вручную.

Вы можете использовать командную строку dp4j, чтобы ответить на ваш вопрос:

    $ javac -cp ../dp4j-1.2-SNAPSHOT-jar-with-dependencies.jar -All -Averbose=true MyClass.java
MyClass.java:7: Note: 
public class MyClass {

public MyClass() {
    super();
}

public void myMethod(Object... args) {
    System.out.println("this is myMethod");
}

@com.dp4j.Reflect()
public void invokeMyMethod() throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException, java.lang.IllegalArgumentException {
    final java.lang.reflect.Method myMethodWithArrayMethod = Class.forName("MyClass").getDeclaredMethod("myMethod", .java.lang.Object[].class);
    myMethodWithArrayMethod.setAccessible(true);
    myMethodWithArrayMethod.invoke(this, new .java.lang.Object[1][]{new .java.lang.Object[2][]{"hi", "there"}});
}

public static void main(String... args) throws Exception {
    new MyClass().invokeMyMethod();
}
}
public void invokeMyMethod() {
            ^

$ java MyClass
this is myMethod
Другие вопросы по тегам