#java #reflection #java-8
#java #отражение #java-8
Вопрос:
Я новичок в концепции отражения Java. Мне нужно получить доступ к одному методу из определенного класса, используя отражение Java. Этот метод имеет три разных типа аргументов, подобных этому,
public void print(int start, String middle, int end) {
System.out.println(start);
System.out.println(middle);
System.out.println(end);
}
Я попытался вызвать этот метод следующим образом,
...
method.invoke(null, "middle", null);
...
Я получил исключение IllegalArgumentException. Я знаю, что значение null приемлемо для аргументов типа оболочки, но я просто попробовал этот метод, чтобы узнать, как он работает.
Итак, мой главный вопрос: как передать значение примитивного типа этому аргументу метода через отражение? кроме того, как передать значение по умолчанию для аргументов примитивного типа через отражение? (например: предположим, мне не нужно значение end arg во время выполнения, тогда как передать 0 для end arg)
Есть ли какой-либо способ решить эту проблему?
Комментарии:
1. Не могли бы вы поделиться полным stracktrace?
2. Примитивный тип не может быть
null
. Если вы хотите использоватьnull
в качестве параметра, вам придется изменить значениеint
наInteger
.3. Передайте an
Integer
; вероятно, вы также можете просто передатьint
значение и позволить автоматической блокировке автоматически превратить его в anInteger
. Так что, если бы вы вызвалиprint(0,"xxx",1)
, просто используйтеprintMethod.invoke(0,"xxx",1)
илиprintMethod.invoke(Integer.valueOf(0), "xxx", Integer.valueOf(1))
4. Ваша проблема не имеет ничего общего с примитивными типами. Поскольку этого метода нет
static
, вы должны предоставить объект для вызова метода, так же просто, какmethod.invoke(object, 100, "middle", 42)
. Даже дляstatic
методов необходим первый аргумент, как и сигнатура методаinvoke(Object obj, Object... args)
, поэтому вам придется вставлять anull
в начале дляstatic
методов, за которыми следуют аргументы метода.
Ответ №1:
Предположим, что у вас есть этот класс:
public class SomeClass {
public void print(int start, String middle, int end) {
System.out.println(start);
System.out.println(middle);
System.out.println(end);
}
}
Вы можете использовать следующий код, чтобы:
- Создайте экземпляр класса с помощью отражения
- Извлеките нужный метод
- Вызовите нужный метод, используя отражение
public class SomeOtherClass {
public static void main(String... args) {
try {
var instance = Class
.forName(SomeClass.class.getName())
.getConstructor()
.newInstance();
var printMethod = SomeClass.class.getMethod("print", int.class, String.class, int.class);
printMethod.invoke(instance, 0, "it's me", 0);
} catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
System.err.println("An error has occurred while accessing method");
e.printStackTrace();
}
}
}
Обратите внимание, что для примитивных значений нет необходимости передавать is null
. В этих случаях вам необходимо указать значение, что, в свою очередь, означает рефлективный вызов метода следующим образом:
printMethod.invoke(instance, 0, "it's me", 0);
Обратите внимание, что это будет то же самое, что и прямой вызов метода, так как в этом случае попытка передать в null
качестве аргумента метода целые числа приведет к ошибке компиляции.
Комментарии:
1. Привет, @akortex91 . Спасибо за ответ. В этом примере вы получаете и вызываете метод напрямую, используя имя метода. Но в моем случае класс имеет список методов, я получаю этот конкретный метод, используя имя метода. Предположим, что у конкретного метода есть 3 аргумента, но у меня есть только 2 значения. Я попробовал этот код
Object[] input = new Object[method.getParameterCount()]; method.invoke(cls.newInstance(), input);
В этом случае, давайте предположим, что входной массив выглядит следующим образом после вставки 2 значений[1, "hi"];
, тогда какой тип значения мне нужно передать для 3-го аргумента?