10

問題:動的言語(Groovy、JavaScriptなど)と同じように、Javaオブジェクトの任意のプロパティ/フィールドにJavaで一般的にアクセスできるようにしたいと思います。この配管コードを書いている時点では、それがどのタイプのオブジェクトであるか、またはプロパティ/フィールド名が何であるかはわかりません。しかし、私はそれを使用するときにプロパティ/フィールド名を知っています。

私の現在の解決策:これまでのところjava.beans.Introspector、Bean / POJOのプロパティを取得し、それらをとして公開するために使用する単純なラッパークラスを作成しましたMap<String, Object>。粗雑ですが、単純なケースで機能します。

私の質問は、リフレクション/マップへの変換以外に、この問題に取り組むための他の方法論は何ですか?

javax.script.*この道をさらに進む前に、Rhinoから何かを共食いする方法を誰かが知っているかどうか、またはおそらくこの概念の実装をよく考えているかどうかを知りたいと思います。あるいは、私が考えていなかったまったく異なるアプローチかもしれません。

編集:はい、私はリフレクションに精通しています(とにかく、Introspectorが内部で使用しているものだと思います)。他によく考えられた解決策があるかどうか、私はただ興味がありました。

編集2:最も一般的な回答には、1)直接またはヘルパークラスを介したリフレクション、および/または2)目的のクラスメンバーを実装するインターフェイスへのマッピングが含まれるようです。Groovyの活用についてのコメントには本当に興味があります。Groovyには真のダックタイピングがあり、JVM言語であるため、Groovyで単純なヘルパーを作成し、Javaから呼び出す方法はありますか?これは本当にクールで、おそらくより柔軟で、パフォーマンスが向上します。

回答:マイクの回答は、最も近い完全な概念であるため、最高のものとしてマークしました。私はおそらくこの特定のケースではそのルートに行きませんが、それは確かに有用なアプローチです。そこにも役立つ情報がたくさんあるので、これを見ている人は必ずここの会話を読んでください。

ありがとう!

4

3 に答える 3

10

公開するAPIのセットがわかっている場合、たとえば、lengthメソッドとイテレーターメソッドにアクセスする必要がある場合は、インターフェイスを定義できます。

public interface TheInterfaceIWant {
  int length();
  void quack();
}

このインターフェースを使用して、このインターフェースを実装していないインスタンスの対応するメソッドにアクセスできるようにする場合は、プロキシクラスを使用できます:http://download.oracle.com/javase/1.4.2/docs/api/java /lang/reflect/Proxy.html

したがって、プロキシを作成します

final Object aDuck = ...;
TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
    TheInterfaceIWant.class.getClassLoader(),
    new Class[] { TheInterfaceIWant.class },
    new InvocationHandler() {
      public Object invoke(
          Object proxy, Method method, Object[] args)
          throws Throwable {
        return aDuck.getClass().getMethod(
            method.getName(), method.getParameterTypes()).invoke(aDuck, args);
      }
    });

次に、動的に型指定された言語のアヒルと同じようにラッパーを使用できます。

if (aDuckWrapper.length() > 0) {
  aDuckWrapper.quack();
}

ラッパーを使用して「Quack」を4回出力する、実行可能な全長の例を次に示します。

import java.lang.reflect.*;

public class Duck {

  // The interface we use to access the duck typed object.
  public interface TheInterfaceIWant {
    int length();
    void quack();
  }

  // The underlying instance that does not implement TheInterfaceIWant!
  static final class Foo {
    public int length() { return 4; }
    public void quack() { System.out.println("Quack"); }
  }

  public static void main(String[] args) throws Exception {
    // Create an instance but cast away all useful type info.
    final Object aDuck = new Foo();

    TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
        TheInterfaceIWant.class.getClassLoader(),
        new Class[] { TheInterfaceIWant.class },
        new InvocationHandler() {
          public Object invoke(
              Object proxy, Method method, Object[] args)
              throws Throwable {
            return aDuck.getClass().getMethod(
                method.getName(), method.getParameterTypes()).invoke(aDuck, args);
          }
        });

    for (int n = aDuckWrapper.length(); --n >= 0;) {
      // Calling aDuck.quack() here would be invalid since its an Object.
      aDuckWrapper.quack();
    }
  }
}
于 2010-12-02T00:39:15.763 に答える
1

型消去を活用する(乱用する?)タイプの消去を利用する、私が今出会ったもう1つの方法は、一種の興味深いものです。

http://rickyclarkson.blogspot.com/2006/07/duck-typing-in-java-and-no-reflection.html

これが単にインターフェースを直接使用することとは大きく異なることを私が購入するかどうかはわかりませんが、おそらく他の誰かにとっては便利です。

于 2010-12-02T14:56:28.047 に答える
0

java.lang.ClassのメソッドとリフレクションAPIを見てください:java.lang.reflect。*

于 2010-12-01T23:54:32.717 に答える