#java #reflection
#ява #отражение #java — язык
Вопрос:
Вы можете определить метод, который будет принимать все, что угодно (Object... arguments)
но, если вы вызовете его с помощью ("A", "B")
и (["A", "B"])
, значение arguments
будет таким же ["A", "B"]
, т. Е. исходная подпись будет потеряна.
Есть ли какой-нибудь способ сохранить это?
P.S. Зачем мне это нужно:
Запомнить вызываемый метод и аргументы и позже ответить на него с помощью отражения. Пример, когда он ломается:
Есть объект с методом, который я хотел бы вызвать позже:
MyObj {
myMeth (String[] array) {...}
}
myObj = new MyObj()
Я говорю компьютеру вызвать его позже с некоторыми аргументами.
callLater(myObj, "myMeth", ["A", "B"])
Он запоминает это, и пользователи пытаются найти фактический метод и вызвать его.
И это не удается, потому что оригинальная подпись потерялась, и вместо (String[])
нее пытаются найти (String, String)
.
Комментарии:
1. Если я правильно помню, в reflection переменные аргументы всегда обрабатываются как массивы. Таким образом, вам нужно иметь возможность искать
Object[]
в качестве параметров метода2. «Оригинальная подпись будет утеряна» ничего не значит. Это не потеряно. Он просто вызывается с помощью двух разных списков аргументов, в чем и заключается вся идея. Непонятно, о чем на самом деле ваш вопрос.
Ответ №1:
Такого рода двусмысленность устраняется на стороне вызывающей стороны с помощью приведений. В этом случае вы должны сначала привести массив к (Object)
, чтобы он обрабатывался как аргумент varargs. например, передать массив в качестве одного аргумента:
callLater(myObj, "myMeth", (Object) new String[] {"A", "B"});
Для передачи двух аргументов:
callLater(myObj, "myMeth", (Object[]) new String[] {"A", "B"});
или просто:
callLater(myObj, "myMeth", "A", "B");
Комментарии:
1. Спасибо, но это не очень удобно, есть ли способ получше? Я хотел бы использовать его как DSL и сохранить его простым и приятным.
2. Если вы хотите что-то «более приятное», вам придется предоставить две версии (названные по-разному; не могут быть перегружены) вашего метода: одну, которая принимает varargs, и другую, которая принимает массив напрямую.
3. Пробовал, компилятор запрещает иметь два метода
(Object... data)
и(Object[] data)
с одинаковым именем.4. Да, вот почему я сказал «названный по-другому». 😀