Skip to content

Define annotations

Java language uses @interface syntax to define annotations ( Annotation ). Its format is as follows:

java
public @interface Report {
  int type() default 0;
  String level() default "info";
  String value() default "";
}

Annotated parameters are similar to parameterless methods, and you can use default to set a default value (strongly recommended). The most commonly used parameters should be named value .

meta-annotation

Some annotations can modify other annotations, and these annotations are called meta annotations. The Java standard library has defined some meta-annotations. We only need to use meta-annotations and usually do not need to write meta-annotations ourselves.

@Target

The most commonly used meta-annotation is @Target . Use @Target to define where Annotation can be applied to the source code:

  • Class or interface: ElementType.TYPE ;
  • Field: ElementType.FIELD ;
  • Method: ElementType.METHOD ;
  • Constructor: ElementType.CONSTRUCTOR ;
  • Method parameters: ElementType.PARAMETER .

For example, to define that the annotation @Report can be used on a method, we must add a @Target(ElementType.METHOD) :

java
@Target(ElementType.METHOD)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

The definition annotation @Report can be used on methods or fields, and the @Target annotation parameters can be turned into arrays { ElementType.METHOD, ElementType.FIELD } :

java
@Target({
    ElementType.METHOD,
    ElementType.FIELD
})
public @interface Report {
    ...
}

In fact, value defined by @Target is ElementType[] array. When there is only one element, the array writing method can be omitted.

@Retention

Another important meta-annotation @Retention defines the life cycle of Annotation :

  • Compile time only: RetentionPolicy.SOURCE ;
  • Only class files: RetentionPolicy.CLASS ;
  • Runtime: RetentionPolicy.RUNTIME .

If @Retention does not exist, the Annotation defaults to CLASS . Because usually our custom Annotation is RUNTIME , so be sure to add @Retention(RetentionPolicy.RUNTIME) This meta-annotation:

java
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

@Repeatable

Use the @Repeatable meta-annotation to define whether Annotation is repeatable. This annotation is not particularly widely used.

java
@Repeatable(Reports.class)
@Target(ElementType.TYPE)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

@Target(ElementType.TYPE)
public @interface Reports {
    Report[] value();
}

After being modified @Repeatable , you can add multiple @Report annotations at a certain type declaration:

java
@Report(type=1, level="debug")
@Report(type=2, level="warning")
public class Hello {
}

@Inherited

Use @Inherited to define whether a subclass can inherit Annotation defined by the parent class. @Inherited is only valid for @Target(ElementType.TYPE) type annotation , and only for class inheritance, and is invalid for interface inheritance:

java
@Inherited
@Target(ElementType.TYPE)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

When using, if a class uses @Report :

java
@Report(type=1)
public class Person {
}

Then its subclasses also define this annotation by default:

java
public class Student extends Person {
}

How to define annotation

Let’s summarize the steps to define Annotation :

The first step is to define the annotation with @interface :

java
public @interface Report {
}

The second step is to add parameters and default values:

java
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

Define the most commonly used parameters as value() , and it is recommended that all parameters be set to default values.

The third step is to configure the annotation using meta-annotations:

java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

Among them, @Target and @Retention must be set, and @Retention is generally set to RUNTIME , because our custom annotations usually require reading during runtime. Under normal circumstances, there is no need to write @Inherited and @Repeatable .

Summary

Java uses @interface to define annotations;

Multiple parameters and default values can be defined, and core parameters use value names;

@Target must be set to specify the scope to Annotation can be applied;

should be set @Retention(RetentionPolicy.RUNTIME) It is convenient to read the Annotation during runtime.

Define annotations has loaded