Отражение Java: getMethod (метод String, Object []. Class) не работает - PullRequest
12 голосов
/ 28 марта 2011

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

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 ]

12 голосов
/ 28 марта 2011

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

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

 s.invoke(this, ex);

на эту

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

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

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

12 голосов
/ 28 марта 2011

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

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

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

Причина, по которой ваш текущий код не работает, состоит в том, чтобы сделатьс тем, как varadic методы реализованы в 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 .

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

1 голос
/ 28 марта 2011

Вы можете использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...