How @Target(ElementType.ANNOTATION_TYPE) works

Java annotations are marked with a @Target annotation to declare possible joinpoints which can be decorated by that annotation. Values TYPE, FIELD, METHOD, etc. of the ElementType enum are clear and simply understandable.

Question

WHY to use @Target(ANNOTATION_TYPE) value? What are the annotated annotations good for? What is their contribution? Give me an explanation of an idea how it works and why I should use it. Some already existing and well-known example of its usage would be great too.


You can use an annotated annotation to create a meta-annotation, for example consider this usage of @Transactional in Spring:

/**
 * Shortcut and more descriptive "alias" for {@code @Transactional(propagation = Propagation.MANDATORY)}.
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(propagation = Propagation.MANDATORY)
public @interface RequiresExistingTransaction {
}

When you enable Spring to process the @Transactional annotation, it will look for classes and methods that carry @Transactional or any meta-annotation of it (an annotation that is annotated with @Transactional).

Anyway this was just one concrete example how one can make use of an annotated annotation. I guess it's mostly frameworks like Spring where it makes sense to use them.


Each annotation annotated by @Target(ElementType.ANNOTATION_TYPE) is called Meta-annotation. That means, you can define your own custom annotations that are an amalgamation of many annotations combined into one annotation to create composed annotations.

A good example from Android world is StringDef

Denotes that the annotated String element, represents a logical type and that its value should be one of the explicitly named constants.

@Retention(SOURCE)
@StringDef({POWER_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE}) 
public @interface ServicesName {}

public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";

Code inspector will treat @ServicesName and @WeekDays in the same way as @StringDef. As a result we can create as much named StringDef's as we need and override set of constants. @Target(ElementType.ANNOTATION_TYPE) it is a tool that allows to extend the use of annotations.