0

メソッドの配列を取り込んでおり、それらをチェーンして、作業中のオブジェクトを変更したいと考えています。

たとえば、私はから始めます

"getStuff().get(1).get(3).setMoreStuff().put(stuff,6)"

メソッドと呼ばれる配列に分割し、各メソッド内のパラメーターをクリーンアップして、これを変更しようとします。

Object res = this;
String[] methods = targetString.split("\\.(?=\\D)");
for (String m : methods){

    List<Object> params = new ArrayList<Object>();
    List<Object> params = new ArrayList<Object>();

                    for (String p : m.split("\\(|,|\\)")) {
                        try {
                            if (p.indexOf(".") != -1){
                                double tempD = Double.parseDouble(p);
                                params.add(tempD);
                            } else {
                                int tempP = Integer.parseInt(p);
                                params.add(tempP);
                            }
                        } catch (Exception ex) { //not a number
                            params.add(p);
                        }
                    }
    switch (params.size()) {
        case 1:
            res = res.getClass().getMethod(
                            params.get(0)
                                   ).invoke(res);
            break;
        case 2:
            res = res.getClass().getMethod(
                            params.get(0),
                            params.get(1).getClass()
                                   ).invoke(res, params.get(1));
            break;
        case 3:
            res = res.getClass().getMethod(
                            params.get(0), 
                            params.get(1).getClass(),           
                            params.get(2).getClass()
                                   ).invoke(res, params.get(1), params.get(2));
                                break; 
    }

最後に、 res が期待どおりに変更されていることに気付きました。すべてのゲッターとセッターが正しく呼び出されます。しかし、もちろん、"this" が参照する基になるオブジェクトは変更されていません!

最初の行で作成したコピーのゲッターとセッターを呼び出しているだけだと思います。

今は使えない

this.getClass().getMethod(...).invoke(...) 

この呼び出しによって返されたオブジェクトに対して同じ getMethod を呼び出す必要があるためです。

明確にするために:

Object res = this;

これへの「ポインタ」を作成します。だから私が電話するとき

res.getStuff().setStuff(foo)

これも変更されます。

しかし、私が電話すると

res = res.getStuff();
res = res.setStuff();

私のループで行うように、これは参照する基になるオブジェクトを変更しませんか?

編集:リクエストに応じてより多くのコードを含めました。

Edit2:私の問題を明確にするために、別の例を追加しました。

Edit3:コードを追加しようとしましたが、すべてのクラスを含めずに動作するプログラムを追加するのは少し難しいです

4

2 に答える 2

2

あなたの一般的なアプローチは問題ないはずです(パラメーター変換へのアプローチはやや醜いですが)-おそらく問題を引き起こしているのは詳細です。メソッドを呼び出して、後で違いを確認する短いが完全なプログラムを次に示します。

import java.lang.reflect.*;

class Person {
    private String name = "default";

    public String getName() {
        return name;
    }

    // Obviously this would normally take a parameter
    public void setName() {
        name = "name has been set";
    }
}

class Test {

    private Person person = new Person();

    public Person getPerson() {
        return person;
    }

    // Note that we're only declaring throws Exception for convenience
    // here - diagnostic code only, *not* production code!
    public void callMethods(String... methodNames) throws Exception {
        Object res = this;
        for (String methodName : methodNames) {
            Method method = res.getClass().getMethod(methodName);
            res = method.invoke(res);
        }
    }

    public static void main(String[] args) throws Exception {
        Test test = new Test();
        test.callMethods("getPerson", "setName");
        System.out.println(test.getPerson().getName());
    }
}

出力は、予想どおり「名前が設定されました」です。したがって、コードを少しずつ単純化できるかどうかを確認し、余分な依存関係などを削除して、同様に短いが完全なものが得られるまで、それは機能しません。やっていくうちに、実際に問題が見つかると思います。

于 2013-10-01T06:36:48.223 に答える