Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it not possible to extend annotations in Java?

People also ask

Is it possible to extend annotations?

In Java SE 6, annotations cannot subclass one another, and an annotation is not allowed to extend/implement any interfaces.

What is @inherited annotation in Java?

The @inherited in Java is an annotation used to mark an annotation to be inherited to subclasses of the annotated class. The @inherited is a built-in annotation, as we know that annotations are like a tag that represents metadata which gives the additional information to the compiler.

Do annotations get inherited Java?

Because there is no multiple inheritance in Java, annotations on interfaces cannot be inherited. Even when the annotation is inherited, the application code that retrieves the annotation of a certain element can distinguish between the annotations that are inherited and those that are declared on the entity itself.

Why are annotations used?

Annotations have a number of uses, among them: Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings. Compile-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.


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.


Extensible annotations would effectively add the burden of specifying and maintaing another type system. And this would be a fairly unique type system, so you could not simply apply an OO type paradigm.

Think through all the issues when you introduce polymorphism and inheritance to an annotation (e.g. what happens when sub-annotation changes meta-annotation specs such as retention?)

And all this added complexity for what use-case?

You want to know if a given annotation belongs to a category?

Try this:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    String category();
}

@Category(category="validator")
public @interface MyFooBarValidator {

}

As you can see, you can easily group and categorize annotations without undue pain using the provided facilities.

So, KISS is the reason for not introducing a meta-type type system to the Java language.

[p.s. edit]

I used the String simply for demonstration and in view of an open ended meta annotation. For your own given project, you obviously can use an enum of category types and specify multiple categories ("multiple inheritance") to a given annotation. Do note that the values are entirely bogus and for demonstration purposes only:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    AnnotationCategory[] category();
}
public enum AnnotationCategory {
    GENERAL,
    SEMANTICS,
    VALIDATION,
    ETC
}

@Category(category={AnnotationCategory.GENERAL, AnnotationCategory.SEMANTICS})
public @interface FooBarAnnotation {

}


In a sense you already have it with Annotations - meta Annotations. If you annotate an annotation with meta information, that is in many ways equivalent to extending an additional interface. Annotations are interfaces, so polymorphism doesn't really come into play, and since they are static in nature, there can be no runtime dynamic dispatching.

In your validator example, you could just on the annotation get the annotated type and see if it has a validator meta-annotation.

The only use case I could see that inheritance would help is if you wanted to be able to get the annotation by super type, but that would add a whole bunch of complexity, because a given method or type may have two such annotations on it, meaning that an array would have to be returned instead of just a single object.

So I think the ultimate answer is that the use cases are esoteric and complicate more standard use cases making it not worth it.


The designers of Java annotation support made a number of "simplifications" to the detriment of the Java community.

  1. No annotations subtypes makes many complex annotations unnecessarily ugly. One cannot simply have an attribute within an annotations that can hold one of three things. One needs to have three separate attributes, which confuses developers and requires runtime validation to ensure that only one of the three is used.

  2. Only one annotation of a given type per site. This has lead to the completely unnecessary collection annotation pattern. @Validation and @Validations, @Image and @Images, etc.

The second one is being remedied in Java 8, but its too late. Many frameworks have been written based on what was possible in Java 5 and now these API warts are here to stay for a good long time.