1

クラス内のメソッドの数が変わる可能性があるため、コードを別のメソッドに送信する必要があるため、リフレクションを使用します。benchmarkMethods.get(i).invoke(set, null);しかし、問題は、匿名クラスが最終変数しか渡せない可能性があるため、ループでそれらを列挙できないことです。この場合、どうすればよいですか?

public void RunAllBenchmarks(final Object set, boolean randomOrder) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    final List<Method> benchmarkMethods = new ArrayList<Method >();
    final Class benchClass = set.getClass();
    Method[] methods = benchClass.getDeclaredMethods();
    for (int i = 0; i < methods.length; i++){
        Annotation[] annotations = methods[i].getAnnotations();
        if (annotations.length != 0){
            for (int j = 0; j < annotations.length; j++)
            if (annotations[j].annotationType().toString().contentEquals("interface Benchmark"))
                benchmarkMethods.add(methods[i]);
        }
    }
    for (int i = 0; i < benchmarkMethods.size(); i++){
        String name = null;
        Method method = benchmarkMethods.listIterator().next();
        MeasureAndRecord(name, new IFunc() {
            @Override
            public Object onEvent() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {

                return benchmarkMethods.get(i).invoke(set, null);
            }
        });

    }

    PrintWriter writer = new PrintWriter(System.out);
    PrintResults(writer);
}
4

3 に答える 3

1

追加すると思ったのですが、非最終変数を匿名クラスに渡すために使用するトリックがあります。あなたが上で書いたコードの一部を取り上げて、私はそれを行う方法を示すためにいくつかの小さな変更を加えました.

私はここmeasureAndRecordがメソッドであると仮定しました (私はそれを示すために最初の文字を大文字にしました)、それIFuncはあなたが匿名拡張を作成しているクラスです。また、それMethod method ...が匿名クラスに渡したいメソッドであると想定しています (コードでは何もしないため)。

ここでの秘訣はinit、変数を渡すことができ (最終または非最終)、返さthisれる (この場合は匿名クラス) と呼ばれる新しいメソッドを追加することです。何が起こるかというと、匿名クラスが呼び出され、initメソッドがすぐに呼び出され、オブジェクト (必要に応じて IFunc) が返されて使用されます。

構築時に (割り当て前に) メソッドを呼び出す必要があり、この方法でメソッドを連鎖させることはできません。その理由は、オブジェクトが最初のメソッド呼び出しから返されると、それは IFunc であり、作成した匿名サブクラスではないため、Java はその後オーバーライドされたメソッド以外は何も認識しなくなります。init

とにかく遊びましょう。少しチートだとしても、とても便利だと思います。Java 8 が登場し、事実上最終的な変数を渡すことができるようになったとしても、これは引き続き可変変数で機能します。

...

for (int i = 0; i < benchmarkMethods.size(); i++) {
    String name = null;
    Method method = benchmarkMethods.get(i); // Assumption on my part

    measureAndRecord(name, new IFunc() {
        // Anonymous class variables matching what we want to pass
        Method method;
        int i;

        // Cheating "Constructor"
        public IFunc init (Method method, int i) {
            this.method = method;
            this.i = i;
            return this; // Must return this for assignment
        }

        @Override
        public Object onEvent() throws InvocationTargetException,    
            IllegalAccessException, NoSuchMethodException {
                return method.invoke(set, null);
            }
        }.init(method, i)); // Note that init is called BEFORE assignment
    }
}

...
于 2014-02-25T11:58:18.527 に答える
0

アプローチは、匿名の内部クラスを回避することです。MethodIFunc implements IFuncつまり、そのonEvent()ieでメソッドを呼び出すクラスを持っている

for (...) {
    Method method = ...

    // this class calls method.invoke(..) inside its onEvent() method
    MethodIFunc mi = new MethodIFunc(method, set);
    MeasureAndRecord(name, mi);
}

for-loop別のアプローチ(ところで:これは実際のコードではないと思いますが、2番目に二重の反復があります)はfor-each、変数をfinalとして宣言できるようにするステートメントを使用することです:

for (final Method method : benchmarkMethods) {
    ...
    MeasureAndRecord(name, new IFunc() {
        @Override
        public Object onEvent() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
            return method.invoke(set, (Object[]) null);
        }
    });

}
于 2013-07-29T09:53:08.123 に答える