5

How to add the @Override annotation to a method while creating the class using javaassist?

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:");

This code is throwing exception as follows:

 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
Lakshmi
  • 81
  • 2
  • 8

3 Answers3

7

@Override isn't a runtime annotation so even if you could add it, it wouldn't make any difference whatsoever.

For annotations that do have a runtime effect (RetentionPolicy.RUNTIME), you can take a look at this question.

Community
  • 1
  • 1
biziclop
  • 48,926
  • 12
  • 77
  • 104
3

Short Version

It isn't interesting to add the annotation. Because as this has @java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE), it will not make any difference. So, you don't need to care about this issue.

I would care with annotations that has @java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME) retention.

Long Version

This anntotation has @java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE) retention meaning it will not change anything even if you add it with JAVASSIST when you are generating some classes to use during runtime.

The annotation doesn't has any influence on the code. When Java generates the sources this is already stripped out. As JAVASSIST generates code it makes no sense add it.

According documentation, retention can be configured as:

  • CLASS Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.
  • RUNTIME Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
  • SOURCE Annotations are to be discarded by the compiler.

In JAVASSIST it would be interesting to add the RUNTIME or CLASS annotations (but for CLASS it would not be that interesting, see here).

Community
  • 1
  • 1
Francisco Spaeth
  • 23,493
  • 7
  • 67
  • 106
2

@Override is only useful to the compiler.

It tells the compiler to ensure that the annotated method either:

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

This becomes of particular importance when interfaces or superclasses change. Your class may otherwise compile, but the method you think is defining functionality on the interface or the superclass may no longer be doing that.

So the @Override annotation lets the compiler bark at you in that case.

Edit

Example:

public interface Foo {
    void bar();
}

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

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

Now, let's say Foo and FooImpl change:

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

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

You're MyFooExtension class would still compile, yet the "bar()" method in that class would never be called. Thus your method is useless. If you add the @Override annotation, you'd get a compile error telling you that no method "void bar()" is being overriden, and you would have to fix your class in order to get it to compile.

Matt
  • 11,523
  • 2
  • 23
  • 33
  • If an interface changes, compilation would fail anyway. – biziclop Jul 03 '12 at 20:28
  • Not necessarily. What if you're extending a base class which implements the interface. See my edit. – Matt Jul 04 '12 at 00:49
  • That scenario would be exactly the same without the interface. @Override is only really useful if you're overriding a non-abstract method. (Although of course you can still use it with abstract methods, but that's just a convenience thing.) – biziclop Jul 04 '12 at 09:26
  • i would recommend using it with abstract methods. What if the base class removes an abstract method (without adding another one back in). Your subclass would still compile without an @Override annotation, and you'd have no indication that the behavior might change. – Matt Jul 04 '12 at 13:47
  • Sure, I'd recommend using it with all methods, overridden or implemented. It costs nothing after all. – biziclop Jul 04 '12 at 15:10