Я работаю над динамическим вызовом кода через интерпретатор, и я попадаю в липкие уродливые области разрешения метода, как описано в разделе JLS 15.12.
"Легкий" способ выбора метода - это когда вы знаете точные типы всех аргументов, после чего вы можете использовать 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);
}
}