如何在使用javassist创建.class文件时将@Override注释添加到方法?

时间:2012-07-03 14:29:06

标签: java javassist

如何在使用javaassist创建类时向方法添加@Override注释?

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

3 个答案:

答案 0 :(得分:7)

@Override不是运行时注释,所以即使你可以添加它,它也不会有任何区别。

对于具有运行时效果(RetentionPolicy.RUNTIME)的注释,您可以查看this question

答案 1 :(得分:3)

短版

添加注释并不感兴趣。因为它有@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE),所以没有任何区别。所以,你不需要关心这个问题。

我会关注@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)保留的注释。

长版

此anntotation具有@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)保留意味着即使您在生成运行期间要生成的某些类时使用JAVASSIST添加它也不会更改任何内容。

注释对代码没有任何影响。当Java生成源时,这已被剥离。由于JAVASSIST生成代码,因此无需添加它。

根据documentation,保留可以配置为:

  • CLASS 注释将由编译器记录在类文件中,但不需要在运行时由VM保留。
  • RUNTIME 注释将由编译器记录在类文件中,并在运行时由VM保留,因此可以反射性地读取它们。
  • SOURCE 编译器将丢弃注释。

在JAVASSIST中添加 RUNTIME CLASS 注释会很有趣(但对于CLASS来说,它不会那么有趣,请参阅here)。< / p>

答案 2 :(得分: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()”被覆盖,你必须修复你的类才能让它编译。<​​/ p>