How @Target(ElementType.ANNOTATION_TYPE) works
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.
For example, if annotation looks like
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeAnnotation {
String description() default "This is example for class annotation";
}
compiler will complane in this situation
@SomeAnnotation
public class SomeClass {
@SomeAnnotation // here it's complaning
public void someMethod(){}
}
If you change
@Target(ElementType.TYPE)
to
@Target({ElementType.METHOD, ElementType.TYPE})
it won't complain anymore.