2

私が構築している小さなフレームワークで、Javassist を使用して特定の抽象クラスを非抽象クラスに変更したいと考えています。必要な動的に生成されたコードを実装するために、すべての抽象メソッドを非抽象メソッドに変換しました。しかし、クラスを非抽象化することにまだ成功していません。私が試したことは、これに似たものです:

c非抽象にしたいクラスだとしましょう。だから私は書いた:

public void instrument(Class c) {
    ...//some ignored exception management
    CtClass ctClass = ClassPool.getDefault().get(c.getName());
    ctClass.setModifiers(c.getModifiers() & ~Modifier.ABSTRACT);  
    return ctClass.toClass().newInstance();
}

ただし、呼び出しは次のとおりです。

ctClass.toClass();

以下を上げていますCannotCompileException

"attempted  duplicate class definition for name: <class_name>."

これは、クラスのメソッドを呼び出しているため、クラスが既にロードされているためですgetName。これが既存のクラスから取得する必要がある唯一のメカニズムのCtClassようですが、それが正しくない場合は誰か教えてください。このルーチンを多くのクラスに適用する必要があることを考えると、クラスのメソッドを呼び出す代わりにクラスの名前をハードコーディングすることgetNameは、理想的な解決策とは言えません。

これを行うための回避策はありますか?. まったく不可能な場合は、抽象クラスを拡張し、そのコンストラクターを実装し、すべての先祖の抽象メソッドを実装する新しいクラスを動的に生成します (もう少し複雑なので、代わりに元のクラス非抽象)。

4

2 に答える 2

3

既存のクラスを変更するのではなく、拡張クラスを作成しようとしましたか? クラスを作成し、すべてのメソッドを実装し、それを使用setSuperClass()して抽象クラスを拡張します。

于 2011-11-08T10:15:36.737 に答える
1

Classあなたがそれを説明したように、問題はあなたが再定義しようとしているあなたがすでにロードされているということです。クラスローダーによってすでにロードされているクラスを再定義しようとすることは違法です。

1つのオプションは、クラスローダーのちょっとしたトリックを行うことです。既存のクラスがロードされていない新しいクラスローダーを作成し(親はシステムクラスローダーです)、Javassistをロードします(引数を取るCtClass.toClass()メソッドを使用します)。ClassLoader

それが示唆しているように、あなたの目標を達成するためのより良い方法があるかもしれません、そしてサブクラスを作成することはより良い設計かもしれません。抽象クラスの代わりにインターフェースを使用することはオプションですか?その場合、動的プロキシもオプションであり、それらを作成するためにサードパーティのライブラリを必要としないという利点があります。

于 2011-11-25T01:34:16.327 に答える