5

@Overridejavaassistを使用してクラスを作成しているときに、メソッドにアノテーションを追加するにはどうすればよいですか?

ClassPool pool = ClassPool.getDefault();
CtClass ctClasz = pool.makeClass("test.ExampleImpl");
ctClasz.addInterface(pool.get(MyInterface.class.getName()));
CtMethod method = CtNewMethod.make ("@Override public void print() { System.out.println(\"Hello!    \"); }", ctClasz);
ctClasz.addMethod(method);

System.out.println("Implementd: Interfaces:" + ctClasz.getInterfaces());
System.out.println("Methods: " + ctClasz.getMethods());
ctClasz.writeFile("D:");

このコードは次のように例外をスローしています。

 Exception in thread "main" javassist.CannotCompileException: [source error] syntax error    
 near "@Override p"
at javassist.CtNewMethod.make(CtNewMethod.java:78)
at javassist.CtNewMethod.make(CtNewMethod.java:44)
at javaassist.Demo.main(Demo.java:17)
 Caused by: compile error: syntax error near "@Override p"
at javassist.compiler.Parser.parseClassType(Parser.java:983)
at javassist.compiler.Parser.parseFormalType(Parser.java:191)
at javassist.compiler.Parser.parseMember1(Parser.java:51)
at javassist.compiler.Javac.compile(Javac.java:89)
at javassist.CtNewMethod.make(CtNewMethod.java:73)
... 2 more
4

3 に答える 3

7

@Overrideはランタイムアノテーションではないため、追加できたとしても、何の違いもありません。

実行時の効果(RetentionPolicy.RUNTIME)を持つ注釈については、この質問を参照してください。

于 2012-07-03T14:34:42.840 に答える
3

短縮版

注釈を追加するのは面白くありません。これが持っているので@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)、それは何の違いもありません。したがって、この問題を気にする必要はありません。

@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)保持力のあるアノテーションを気にします。

ロングバージョン

この注釈には保持機能があり@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)ます。つまり、実行時に使用するクラスを生成するときに、JAVASSISTを使用して追加しても、何も変更されません。

注釈はコードに影響を与えません。Javaがソースを生成するとき、これはすでに削除されています。JAVASSISTはコードを生成するので、それを追加しても意味がありません。

ドキュメントによると、保持は次のように構成できます。

  • CLASS注釈は、コンパイラによってクラスファイルに記録されますが、実行時にVMによって保持される必要はありません。
  • RUNTIMEアノテーションは、コンパイラによってクラスファイルに記録され、実行時にVMによって保持されるため、反射的に読み取ることができます。
  • SOURCE注釈は、コンパイラーによって破棄されます。

JAVASSISTでは、RUNTIMEまたはCLASSアノテーションを追加することは興味深いでしょう(ただし、CLASSについては、それほど興味深いものではありません。ここを参照してください)。

于 2012-07-03T14:32:46.830 に答える
2

@Overrideは、コンパイラーにのみ役立ちます。

これは、注釈付きメソッドが次のいずれかであることを確認するようにコンパイラーに指示します。

a. Overrides a method on the superclass
b. Implements an interface method.

これは、インターフェイスまたはスーパークラスが変更されたときに特に重要になります。それ以外の場合、クラスはコンパイルされる可能性がありますが、インターフェイスまたはスーパークラスで機能を定義していると思われるメソッドは、それを実行しなくなっている可能性があります。

したがって、@ Overrideアノテーションを使用すると、その場合、コンパイラーはあなたに吠えます。

編集

例:

public interface Foo {
    void bar();
}

public class FooImpl {
    public void bar() { ... }
}

public class MyFooExtension extends FooImpl {
    public void bar() { .... }
}

ここで、FooとFooImplが変更されたとしましょう。

public interface Foo {
    void bar(String input);
}

public class FooImpl {
    public void bar(String input) { ... }
}

MyFooExtensionクラスは引き続きコンパイルされますが、そのクラスの「bar()」メソッドが呼び出されることはありません。したがって、あなたの方法は役に立たない。@Overrideアノテーションを追加すると、メソッド "void bar()"がオーバーライドされていないことを示すコンパイルエラーが発生し、コンパイルするにはクラスを修正する必要があります。

于 2012-07-03T19:06:50.630 に答える