私はインタープリターを介したコードの動的呼び出しに取り組んでおり、JLS セクション 15.12で説明されているように、メソッド解決の厄介な領域に取り組んでいます。
メソッドを選択する「簡単な」方法は、すべての引数の正確な型を知っている場合です。その時点でClass.getDeclaredMethod(String name, Class[] parameterTypes)
. メソッドのアクセシビリティとクラスのスーパークラス/スーパーインターフェースを確認する必要があるかもしれません。
ただし、これは次のケースのいずれもカバーしていないため、役に立ちません。
- ボックス化/ボックス化解除プリミティブ
- サブタイプ
- 可変引数
- null 引数 (インタープリターが別の方法で認識していない限り、任意の型にすることができます。コンパイル時に null をクラス/インターフェイスにキャストすることにより、あいまいさが解消されます)
- プリミティブ型変換 (Java の一部ではありませんが、言語のコンテキストでは許容されます。たとえば、Rhino Javascript ではすべての数値が浮動小数点であるため、Java コードは an を取る可能性があります
int
が、呼び出し元は anint
または a のいずれかの数値を渡しますdouble
)
(最初の 3 つの簡単な例については、以下を参照してください)
そのため、独自のメソッド解決ライブラリを作成する必要があります...
これを支援する有名なフレームワーク ライブラリはありますか?
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);
}
}