16

のようなものを書くとき

doit(43, 44, "hello");

コンパイラは、どのオーバーロードされたメソッドが呼び出されるかを認識しています。リフレクションで同じことをしたいときは、自分自身を知る必要があります。

doit(Integer, double, CharSequence...);

のようなものを介してそれを取得します

Class[] types = {Integer.class, double.class, CharSequence[].class};
declaringClass.getDeclaredMethod("doit", types);

ただ書くことができる何かがすでにあるのだろうか

Method m = getMethod(declaringClass, "doit", 43, 44, "hello");

JLSはこの点で少し複雑なので、誰かがすでにこれを行ったのではないかと思います。


実際、フェーズ1のように、コンパイラーとまったく同じように動作することは不可能です。コンパイラーは、ボックス化とボックス化解除を行わずに一致するメソッドのみを受け入れます。上から私の仮説を呼び出すとき、プリミティブとそのラッパーの区別はすでに失われています(varargsを介して引数を渡すときの自動ボクシングのため)。この問題には解決策がないようですので、無視しましょう。getMethod

答えで示唆されているように、BeanUtils.invokeMethod近づいています。それが何を意味するにせよ、それは最良の一致を見つけることになっています。MethodUtils.getMatchingAccessibleMethodを見ると、

  • varargsについては何も知りません
  • それは非決定論的です

だから私はもっと良いものを探しています。

4

2 に答える 2

1

または、Apache Commons の Bean Utils を使用できます。

public static Method getAccessibleMethod(
        Class clazz,
        String methodName,
        Class[] parameterTypes)

ドキュメントによると:

指定された名前とパラメーターを使用して、アクセス可能なメソッド (つまり、リフレクションを介して呼び出すことができるメソッド) を返します。そのようなメソッドが見つからない場合は、null を返します。これは getAccessibleMethod(Method method) の便利なラッパーです。

パラメータ: clazz - このクラスからメソッド を取得するmethodName - この名前でメソッドを取得する parameterTypes - これらのパラメータ タイプを使用して

実装はアクセス可能なメソッドを取得し、一致するメソッドが見つかるまで階層を上ります。

呼び出しに直接

要求どおりに呼び出しを直接実行するには、同じ API からこのメソッドを使用できます。

public static Object invokeExactMethod(
        Object object,
        String methodName,
        Object[] args,
        Class[] parameterTypes)
        throws
        NoSuchMethodException,
        IllegalAccessException,
        InvocationTargetException

あるいは

public static Object invokeExactMethod(
        Object object,
        String methodName,
        Object[] args)
        throws
        NoSuchMethodException,
        IllegalAccessException,
        InvocationTargetException

最初に使用してメソッドを見つけ、getAccessibleMethod後でそれを呼び出します。

于 2012-08-01T19:09:19.683 に答える
0

これMethodHandleは、シグネチャを使用してオーバーロードされたメソッドを取得する新しい方法です (Java 7):

例:

static class A {
    public String get() {
        return "A";
    }
}

static class B extends A {
    public String get() {
        return "B";
    }
}

public static void main(String[] args) throws Throwable {

    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodType mt = MethodType.methodType(String.class);
    MethodHandle mh = lookup.findVirtual(A.class, "get", mt);;

    System.out.println(mh.invoke(new B()));
}

出力:

B
于 2012-08-01T19:14:18.680 に答える