Я работаю над динамическим вызовом кода через интерпретатор, и я попадаю в липкие уродливые области разрешения метода, как описано в JLS section 15.12.Java: разрешение метода выполнения
«Простой» способ выбора метода - это когда вы знаете точные типы всех аргументов, после чего вы можете использовать Class.getDeclaredMethod(String name, Class[] parameterTypes)
. Возможно, вам нужно проверить доступность метода и суперклассы класса/суперинтерфейсы.
Но это не распространяется на любом из следующих случаев, так что это своего рода бесполезно:
- бокса/распаковка примитивов
- подтипы
- переменной длиной
- нулевого аргумента (который может быть любой тип, если интерпретатор не знает иначе: во время компиляции любая неоднозначность будет устранена путем исключения null в класс/интерфейс)
- преобразование примитивного типа (не является частью Java, но допускается в контекст языков - например. Rhino Javascript, где все числа с плавающей точкой, так что код Java может занять
int
, но вызывающий абонент переходит в номере, который является либоint
илиdouble
)
(см ниже для быстрого примера первых три)
Так что теперь я должен написать свою собственную библиотеку разрешения метода ...
есть ли хорошо известные рамки библиотека, чтобы помочь в этом?
package com.example.test.reflect;
import java.lang.reflect.Method;
public class MethodResolutionTest {
public void compute(int i) { /* implementation... */ }
public void compute(Long l) { /* implementation... */ }
public void compute(Object obj) { /* implementation... */ }
public void compute(String... strings) { /* implementation... */ }
public static void main(String[] args) {
Class<?> cl = MethodResolutionTest.class;
/* these succeed */
findAndPrintMethod(cl, "compute", int.class);
findAndPrintMethod(cl, "compute", Long.class);
findAndPrintMethod(cl, "compute", Object.class);
findAndPrintMethod(cl, "compute", String[].class);
/* these fail */
findAndPrintMethod(cl, "compute", Integer.class);
findAndPrintMethod(cl, "compute", long.class);
findAndPrintMethod(cl, "compute", MethodResolutionTest.class);
findAndPrintMethod(cl, "compute", String.class, String.class);
}
private static void findAndPrintMethod(Class<?> objectClass,
String methodName, Class<?>... parameterTypes)
{
try {
Method method = findMethod(objectClass, methodName,
parameterTypes);
System.out.println(method.toString());
}
catch (SecurityException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private static Method findMethod(Class<?> objectClass,
String methodName, Class<?>[] parameterTypes)
throws SecurityException, NoSuchMethodException
{
return objectClass.getDeclaredMethod(methodName, parameterTypes);
}
}
[Этот ответ обрабатывает некоторые ваши случаи, такие как подтипы] (http://stackoverflow.com/questions/2580665/java-getmethod-with-superclass-parameters-in-method/2580699#2580699). –
@Jonathon: Я знаю о isAssignableFrom. У меня есть что-то домашнее, работающее с подтипами и боксом/распаковкой. Затем я начал с варгаров, и это стало неприятно, и я подумал: «Подожди, почему я вообще это делаю?» поэтому я специально ищу существующую библиотеку. (Или, по крайней мере, хороший набор ранее существовавших тестов). В противном случае я могу сделать это самостоятельно, но это большая боль. –
Если вы не найдете сладкую библиотеку, я думаю, что все, что вы делаете, будет уродливым и трудным для чтения. –