1

重複の可能性:
Java クラスは実行時にそれ自体にメソッドを追加できますか?

Javaでクラスの実行時に新しいメソッドを合成することは可能ですか? それを可能にするライブラリはありますか?

4

2 に答える 2

3

バイトコード エンジニアリング ライブラリを超えて、クラスのインターフェイスがあれば、Java のProxyクラスを使用できます。

インターフェースの場合:

public interface Foo {
    void bar();
}

具体的なクラス:

class FooImpl {
    public void bar() {
        System.out.println("foo bar");
    }
}

呼び出されたメソッドを処理するには、次を使用しますInvocationHandler

class FooInvocationHandler implements InvocationHandler {

    private Foo foo;

    FooInvocationHandler(Foo foo) {
        this.foo = foo;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
        if (method.getName().equals("bar"))
            System.out.println("foo me");
            // return null if you don't want to invoke the method below
        }
        return method.invoke(foo, args); // Calls the original method
    }
}

次に、を使用してインスタンスをFooFactory生成およびラップする を作成します。FooImplProxy

public class FooFactory {
    public static Foo createFoo(...) {
        Foo foo = new FooImpl(...);
        foo = Proxy.newProxyInstance(Foo.class.getClassLoader(),
                new Class[] { Foo.class },
                new FooInvocationHandler(foo));
        return foo;
    }
}

FooImplこれにより、次のようにオブジェクトがラップされます。

Foo foo = FooFactory.createFoo(...);
foo.bar();

版画:

foo me
foo bar

これは BCEL ライブラリの代替手段であり、実行時情報からクラスを生成するなど、これを行うことができますが、BCEL ライブラリはネイティブではありません。(1.3以降のすべてに参加しています。Proxyjava.lang.reflect

于 2012-09-18T22:31:49.033 に答える
3

すでにロードされているクラスに? 私の知る限りではありません。

ただし、新しいクラスの生成に関心があるかもしれません。2 つのオプションが表示されます。

  • 私は最近、コードを含む文字列に基づいてクラスを生成し、それをシステムにロードして、そのメイン メソッドを実行するプロジェクトを作成しました。ただし、これにはJDKのインストールが必要です=非常に信頼性が低い
  • BCELを通して。これも悪い点はありますが、全体的には良くなっているようです。メソッドのバイトコードを事前に取得する必要があります。たとえば、メソッドを作成することで、いくつかのトリックを行うことができます

そのようです:

public static void printTest() {
    System.out.println("Hey!");
}

次に、バイトコードを見て、ConstantPool のどこに「Hey!」が表示されているかを確認します。次に、メソッドのバイトコードを取得してバイト配列にキャッシュし、定義済みのバイト + 定数プール (前に調べたもの) を使用してメソッドを動的に作成し、定数プールを文字列で変更します。ただし、より複雑なメソッドの場合、これは非常にトリッキーになります (注: err に変更するなど、呼び出すメソッドまたは取得するフィールドを変更するために同じことができます)。

私が見る限り、良い選択肢は本当にないので、これらはあなたの最善の策です

于 2012-09-18T22:04:28.697 に答える