1

「foo」という名前のオブジェクトがあります (Object foo = new Object())。このオブジェクトを別のメソッドで呼び出したいと思います。このメソッドでは、このオブジェクト名を含む文字列を署名に渡します。オブジェクトの名前を表す文字列を使用して、このオブジェクトを呼び出すにはどうすればよいですか?

シンボルが見つからないというエラーが発生します。

ここにいくつかのコードがあります:

//from main method
Object foo = new Object();
Monitor monitor = new Monitor();
//end main method

class Monitor {
  public Monitor() {
    Manager manager = new Manager();
  }


//IMPORTANT - info.objectName is user input, and for this example it is "foo"

  public void processArgument(Instruction info) {
    if (info.command == "read") int value = manager.read(info.objectName);
  }
}

class Manager {
  public int read(String obj) {
    return obj.getRead();
  }
}

class Object {
  private int value;
  public int getRead() {return value;}
}

私はこれがあまり得意ではありませんが、助けが必要です。これは、厳密なコード共有防止ポリシーを持つクラス用であるため、これをできるだけ抽象化しようとしました。

4

3 に答える 3

0

「foo」という名前のメソッドを呼び出したい場合は、

  1. foo メソッドのクラス オブジェクトを取得します。
  2. Method オブジェクトを返す getDeclaredMethod() を呼び出します。
  3. Method オブジェクトでメソッドを呼び出します。

Class classOfFoo = FooClass.class;

FooClass obj = new FooClass(); //Or may be you have your own object.

classOfFoo.getDeclaredMethod("foo",fooParameter.class).invoke(obj,fooParametersObj);

リフレクション API を確認することをお勧めします。

getDeclaredMethod(String name,Class... parameterTypes)

public Object invoke(Object obj, Object... args)

于 2012-07-17T04:58:00.250 に答える
0

簡潔な答え

Java または JVM では、これはサポートされていません。

ロングアンサー なぜ

与えられたMyCustomObject xxx = new MyCustomObject();

. _ xxx_ MyCustomObject_ String s = "xxx";という名前の参照を JVM で検索する方法がないためxxxです。xxx任意の を指定して参照を検索できる方法はありませんString

重複した質問

Java リフレクション: 名前を入力して見つかった特定のクラスのインスタンスを取得しますか? 参照名で見つからない場合は、メソッドを呼び出すことはできません!

ハッキーな回避策

この参照を自分で何らかのMap<String, T>構造に格納し、その構造を渡して自分で検索することもできますが、それは JVM または言語自体に組み込まれるものではありません。これを強制することはほとんど不可能であり、一部のstaticデータに密結合が発生し、他の多くの設計上の問題により、将来的に多くの頭痛の種が発生します。

于 2012-07-17T04:16:24.093 に答える
0

これをネイティブに行う方法は 2 つありますが、ネイティブではない方法が 1 つあります。

  • If ステートメント
  • ファンクターマップ
  • 反射

オプション1

あなたが持っているのはオプション1です。それはほとんど正しいです。間違った比較方法を使用しているだけです。あなたのものを比較してください

public void processArgument(Instruction info) {
    // this is bad - uses reference comparison
    if (info.command == "read") 
        int value = manager.read(info.objectName);
}

推奨と

public void processArgument(Instruction info) {
    // this is good - actually compares the values
    if (info.command.equals("read"))
        int value = manager.read(info.objectName);
}

info.commandが null の場合、これは例外をスローしないため、次のことを行う方がさらに良いと考える人もいます。個人的には、例外を取得したいので、それは好きではありませんが、多くの人がそれを支持しており、そうするのに完全に正当な理由があります。

public void processArgument(Instruction info) {
    // "read" can never be null, so no null pointer exception here
    if ("read".equals(info) )
        int value = manager.read(info.objectName);
}

もちろん、振る舞いを追加すると、if ステートメントを追加するだけです。

Java 7 では、これを行うことができます。

public void processArgument(Instruction info) {
    switch(info.command) {
        case "read": manager.read(info.objectName); break;
        case "write": manager.write(info.objectName); break;
        default: throw new IllegalArgumentException("Command " + info.command + " not supported");
    }
}

オプション 2

別のオプションは、次のように匿名クラスを利用する Map を使用することです。

// define this somewhere
abstract class Functor {
    Manager m;
    Functor(Manager m) { this.m = m; }
    void execute(Instruction info);
}

// somewhere you have access to
Map<String,Functor> funcs = new HashMap<String,Functor>();

// add this to a static block, or constructor, depending
funcs.put("read", new Functor(manager) {
    public void execute(Instruction info) { m.read(info.objectName); }
});
funcs.put("write", new Functor(manager) {
    public void execute(Instruction info) { m.write(info.objectName); }
}

次に、引数を呼び出すとき

public void processArgument(Instruction info) {
    Functor f = funcs.get(info.command);
    if(f == null) throw new IllegalArgumentException("Operation " + info.command + " not supported");
    f.execute(info);
}

オプション 3

SagarDabas が彼の投稿で概説しているように、リフレクションを使用します。これには特別なアクセス許可が必要な場合があり、正確性オプションの柔軟性が得られないことに注意してください。

于 2012-07-17T17:19:50.037 に答える