Why Is It Not Possible to Extend Annotations in Java

Why is it not possible to extend annotations in Java?

About the reason why it wasn't designed that way you can find the answer in the JSR 175 Design FAQ, where it says:

Why don’t you support annotation subtyping (where one annotation type extends another)?

It complicates the annotation type
system, and makes it much more
difficult to write “Specific Tools”.

“Specific Tools” — Programs that query
known annotation types of arbitrary
external programs. Stub generators,
for example, fall into this category.
These programs will read annotated
classes without loading them into the
virtual machine, but will load
annotation interfaces.

So, yes I guess, the reason is it just KISS. Anyway, it seems this issue (along with many others) are being looked into as part of JSR 308, and you can even find an alternative compiler with this functionality already developed by Mathias Ricken.

How to extend annotations in Java?

This is not possible right now. But in the near future we will support plugins for AndroidAnnotations, so you will be able to add new annotations and corresponding code generators easily.

Is there something like Annotation Inheritance in java?

Unfortunately, no. Apparently it has something to do with programs that read the annotations on a class without loading them all the way. See Why is it not possible to extend annotations in Java?

However, types do inherit the annotations of their superclass if those annotations are @Inherited.

Also, unless you need those methods to interact, you could just stack the annotations on your class:

@Move
@Page
public class myAwesomeClass {}

Is there some reason that wouldn't work for you?

Is class extends annotations of an other?

Annotations are not inherited.

You can read more here: http://fusionsoft-online.com/articles-java-annotations.php

Some other references:
https://stackoverflow.com/a/1644135/1001027
and
https://stackoverflow.com/a/4745820/1001027

Exceptions are annotations which its declaration is annotated with @Inherited.

Why java classes do not inherit annotations from implemented interfaces?

I'd say the reason is that otherwise a multiple-inheritance problem would occur.

Example:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Inherited
public @interface Baz { String value(); }

public interface Foo{
@Baz("baz") void doStuff();
}

public interface Bar{
@Baz("phleem") void doStuff();
}

public class Flipp{
@Baz("flopp") public void doStuff(){}
}

public class MyClass extends Flipp implements Foo, Bar{}

If I do this:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()

what's the result going to be? 'baz', 'phleem' or 'flopp'?


For this reason, annotations on interfaces are rarely useful.

Why can @Repeatable Annotations not be inherited from interfaces

Please recall the documentation of @Inherited:

If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type.

In other words, @Inherited never was intended to be a feature for collecting multiple annotations on a type hierarchy. Instead, you will get the annotation of the most specific type which has an explicit annotation.

In other words, if you change your declaration to

@RepeatableAnnotation("FOO") @RepeatableAnnotation("BAR") class Base {}

@RepeatableAnnotation("C") @RepeatableAnnotation("D")
public class TestClass extends Base implements IntefaceA, IntefaceB {

it won’t change the result; FOO and BAR of Base are not inherited by TestClass as it has the explicit annotation values C and D.

Expanding this to the interface hierarchy would be awkward due to the multiple inheritance and the fact that a super-interface may turn out to be a sub-interface of another super-interface so finding the most specific one is not trivial. This differs heavily from the linear search of the superclass hierarchy.

You may encounter the situation where multiple unrelated annotated interfaces exist but it’s not clear why this ambiguity should be resolved by joining them into one repeated annotation. This would not harmonize with the behavior in all other scenarios.


Note that the answer you have linked is a bit odd as it shows code using a method annotation but method annotations are never inherited, regardless of whether you specified @Inherited or not (an audit tool should generate a warning when you combine @Target(ElementType.METHOD) with @Inherited, imho). @Inherited is relevant for type annotations only.

How do you extend a Java class and change annotations?

Though I'm not sure why you'd want to, you'd need to extend the class, override the methods, and apply the annotations:

public class App
{
public static void main(String[] args) throws NoSuchMethodException
{
Class<MyClass> c = MyClass.class;
MyAnnotation a = c.getMethod("someMethod",null).getAnnotation(MyAnnotation.class);
System.out.println(a.name());

Class<MySubclass> c2 = MySubclass.class;
a = c2.getMethod("someMethod",null).getAnnotation(MyAnnotation.class);
System.out.println(a.name());
}
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {
String name() default "";
}

class MyClass {

@MyAnnotation(name="Some value")
public String someMethod() {
return "Hi!";
}
}

class MySubclass extends MyClass {

@Override
@MyAnnotation(name="Some other value")
public String someMethod() {
return super.someMethod();
}
}

Output:

Some value

Some other value



Related Topics



Leave a reply



Submit