Как вызвать метод main для класса, указанного в String - PullRequest
1 голос
/ 24 апреля 2020

Я пытаюсь вызвать метод main для класса Java, определенного строкой. В реальной программе идентификатор класса будет переменной, но на данный момент я пытаюсь это сделать. Нужный параметр main, newargs имеет тип String [].

try {       
    Class c = Class.forName("Arena");

    Class[] aarg = new Class[1];  
    aarg[0] = String[].class;

    Method m = c.getMethod("main", aarg); // Needs parameter class list
    m.invoke(newargs);
}           
catch (Exception e) {
    System.err.println(e);      
}

Сначала я получаю предупреждение компилятора (Athena - это имя класса, в котором я сейчас работаю):

Note: Athena.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Затем при тестировании я получаю следующее исключение:

java.lang.IllegalArgumentException: wrong number of arguments

Мне кажется, что главное, что я не знаю, как определить параметр main() как массив класса String (не смог найти пример этого), но, может быть, я упускаю больше, чем это.

Ответы [ 3 ]

1 голос
/ 24 апреля 2020

В getMethod() вы предоставляете массив классов длиной 1. Это несколько неверно; это должно работать из-за использования varargs, но это бессмысленно. Метод будет интерпретировать это так же, как просто предоставление одного класса. Буквальное добавление .class к ожидаемым типам и разделение их запятыми должно дать правильный результат. Если бы у вас были String[] и int в качестве параметров в main(), это выглядело бы как c.getMethod("main", String[].class, int.class).

В invoke(), вы можете игнорировать первый параметр и передать null, поскольку main() это static метод. Второй объявлен как параметр varargs, но в моем тесте это не сработало должным образом. Я приведу к одному Object вместо массива длиной 1 Object с. Здесь Object работает как необработанный тип, так как invoke() не информирован о том, какими должны быть его параметры во время компиляции, но может привести их к нужному типу во время выполнения.

Использование varargs в invoke() не работает в этом случае, потому что ожидает тип Object[] или разделенные запятыми значения, которые можно объединить в Object[]. Проблема в том, что String[] является подклассом Object[]. Поэтому вместо интерпретации String[] как одного String[] метода invoke() считает, что вы пытаетесь задать ему набор различных String / Object входов.

Внутренняя логика c:
method.invoke(null, 1, 2, 3) становится Object[] с int элементами. 3 отдельных int параметра
method.invoke(null, "hello", "wow", "ok") становятся Object[] с String элементами. 3 отдельных String параметра
method.invoke(null, String[] { "hello", "wow", "ok" }) становятся Object[] с String элементами. 3 отдельных параметра String, хотя нам нужен только один параметр String[]

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

try {       
    Class<?> c = Class.forName("Test");
    Method m = c.getMethod("main", String[].class); // Needs parameter class list
    String[] input = new String[] { "hello world" };
    m.invoke(null, (Object) input);
}           
catch (Exception e) {
  e.printStackTrace();
}
0 голосов
/ 24 апреля 2020

Я думаю, это сработало бы, если бы тип аарга был String []. Сейчас это класс [].

0 голосов
/ 24 апреля 2020

invoke принимает два аргумента,

  public Object invoke(Object obj, Object... args)

obj объект, лежащий в основе метода, вызывается из аргументов

args аргументов, используемых для вызова метода

Class c = Class.forName("Arena");
String[] params = null;
Method m = c.getMethod("main", String[].class); // Needs parameter class list
m.invoke(null,(Object) params);

Примечание null для invoke, так как основной метод не нуждается в экземпляре.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...