1 yuan notes

1.1 What are meta-annotations

The so-called meta-annotation is actually the annotation that can be annotated to other annotations. The annotation by the annotation is called the combination annotation, and the combination annotation has the function of the upper meta-annotation.

1.2 Four kinds of meta-annotations

There are four standard annotation classes for annotating annotation types in the JDK, called meta-annotations. They are:

  • @Target
  • @Retention
  • @Documented
  • @Inherited

We can use these four meta-annotations to annotate our custom annotation types.

1.3 @ Target annotation

The Target annotation is used to describe the scope of the annotation (that is, where the modified annotation can be used).

The Target annotation indicates the range of objects that can be modified by the annotation class it annotates: Annotations can be used to modify packages, types (classes, interfaces, enumerations, annotation classes), class members (methods, constructors, member variables, enumerated values), method parameters, and local variables (such as loop variables, catch parameters), Using @Target when defining an annotation class makes it clear what objects it can be used to modify, and its range is defined in the ElementType enumeration. The source code

@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.ANNOTATION_TYPE)  
public @interface Target {  
    ElementType[] value();  
}  
Copy the code

ElementType

Public enum ElementType {public enum ElementType {public enum ElementType {public enum ElementType {public enum ElementType { METHOD, // member METHOD, // CONSTRUCTOR, // LOCAL_VARIABLE, // local variable ANNOTATION_TYPE, // annotation class PACKAGE, // Can be used to modify: package TYPE_PARAMETER, // type parameters, JDK 1.8 new TYPE_USE // use type anywhere, JDK 1.8 new}Copy the code

1.4 @ Retention

The purpose of a Reteniton annotation is to describe how long an annotation can be retained in the class it modifies.

Reteniton annotations are used to define how long annotated classes can be retained after they are annotated to other classes. There are three strategies, defined in the RetentionPolicy enumeration. RetentionPolicy

Public enum RetentionPolicy {SOURCE, // RetentionPolicy CLASS, // RetentionPolicy CLASS, // RetentionPolicy CLASS, // RetentionPolicy CLASSCopy the code

Life cycle length SOURCE < CLASS < RUNTIME, where the former works, the latter must work. If you need to retrieve annotation information dynamically at RUNTIME, use RUNTIME annotations only. Use CLASS annotations if you want to do some pre-processing at compile time, such as generating auxiliary code (such as ButterKnife). If you just do some checking operations, such as @Override and @SuppressWarnings, use the SOURCE annotation.

1.5 @ Documented

The Documented annotation describes whether to preserve annotation information when you use the Javadoc tool to generate a help document for a class. To verify @documented, we create a custom annotation:

@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyDocumentedt {

    public String value() default And this is the @documented annotation that you add to your document.;

}
Copy the code

Then create a test class with custom annotations on both methods and classes

@myDocumentedt Public Class MyDocumentedTest {/** * test document * @return String the response
     */
    @MyDocumentedt
    public String test() {return "sdfadsf"; }}Copy the code

Open the Java file directory, open the command line, and enter:

javac .\MyDocumentedt.java .\MyDocumentedTest.java
Copy the code
javadoc -d doc .\MyDocumentedTest.java .\MyDocumentedt.java
Copy the code

index.html

1.6 @ Inherited

Inherited annotations are used to make annotations that are modified by @Inherited Inherited. (If a class uses an annotation modified by @Inherited, its child classes automatically inherit the annotation.) Verify with code to create a custom annotation

@Target({ElementType.TYPE})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MyInherited {
}
Copy the code

validation

@MyInherited
public class A {
    public static void main(String[] args) {
        System.out.println(A.class.getAnnotation(MyInherited.class));
        System.out.println(B.class.getAnnotation(MyInherited.class));
        System.out.println(C.class.getAnnotation(MyInherited.class));
    }
}

class B extends A{
}

class C extends B{
}
Copy the code

You can see the printed information from the console by executing the main method

1.7 Repeat the @repeatable comment

Repeated annotations: This allows the same type annotation to be used multiple times before the same declaration type (class, attribute, or method).

Prior to java8, the same program element could be preceded by at most one annotation of the same type; If you need to use multiple annotations of the same type in front of the same element, you must use annotation containers. Java8 prior to that

public @interface Roles {
    Role[] roles();
}
Copy the code
public @interface Roles {
    Role[] value();
}
Copy the code
public class RoleAnnoTest {
    @Roles(roles = {@Role(roleName = "role1"), @Role(roleName = "role2")})
    public String doString() {return ""; }}Copy the code

Java8 has added repeated annotations, which are used as follows:

public @interface Roles {
    Role[] value();
}
Copy the code
@Repeatable(Roles.class)
public @interface Role {
    String roleName();
}
Copy the code
public class RoleAnnoTest {
    @Role(roleName = "role1")
    @Role(roleName = "role2")
    public String doString() {return ""; }}Copy the code

The difference is that when creating a duplicate annotation Role, @Repeatable points to the stored annotation Roles. When using the Role annotation, you can directly repeat the Role annotation. As you can see from the above examples, Java 8 is a bit more readable for general thinking. However, you still need to define container annotations.

The results obtained by the two methods are the same. Repeated annotations are a simplification that is an illusion: multiple repeated annotations are actually handled by array elements that are the value members of the “container” annotations.

1.8 Type Annotations

Java8 adds TYPE_PARAMETER and TYPE_USE enumeration values to ElementType enumeration so that you can use @target (ElementType_TYPE_USE) to modify annotation definitions, which are called type annotations. Can be used anywhere a type is used.

Prior to java8, annotations could only be used with a variety of program elements (defining classes, defining interfaces, defining methods, defining member variables…). On. Starting with java8, type annotations can be used anywhere a type is used.

TYPE_PARAMETER: indicates that this annotation can be written in the declaration of type parameters.

TYPE_USE: indicates that the annotation can be used wherever the type is used, such as in the following locations:

  • Create an object (with the new keyword)
  • Type conversion
  • Implements the interface using implements
  • Throws exception declarations using throws
public class TypeUserTest {

    public static void main(String[] args) {
        String str = "str";
        Object obj = (@isNotNull Object) str;
    }

}

@Target(ElementType.TYPE_USE)
@interface isNotNull{
}
Copy the code

This ubiquitous annotation allows the compiler to perform more rigorous code checks, which improves the robustness of the program.

2 Custom annotations

Through the above learning has a preliminary understanding of how the meta-annotation, the next step to a custom annotation to understand. Custom annotations

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Name {

    public String value() default "";
}
Copy the code
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sex {

    public enum GenderType {
        Male("Male"),
        Female("Female");
        private String genderStr;
        private GenderType(String arg0) {
            this.genderStr = arg0;
        }
        @Override
        public String toString() {
            return genderStr;
        }
    }
    GenderType gender() default GenderType.Male;
}
Copy the code

An entity class with custom annotations

@Data
public class User {

    @Name(value = "wtj")
    public String name;
    public String age;
    @Sex(gender = Sex.GenderType.Male)
    public String sex;

}
Copy the code

test

public class AnnotionUtils { public static String getInfo(Class<? > cs){ String result =""; Field[] declaredFields = cs.getDeclaredFields(); // Get all fieldsfor (Field field : declaredFields){
            if(field. IsAnnotationPresent (Name. The class)) {/ / get a program element the annotations on the Name annotation = field. The getAnnotation (Name. The class); String value = annotation.value(); result += (field.getName() +":" + value + "\n");
            }
            if(field.isAnnotationPresent(Sex.class)){
                Sex annotation = field.getAnnotation(Sex.class);
                String value = annotation.gender().name();
                result += (field.getName() + ":" + value + "\n"); }}returnresult; } public static void main(String[] args){ String info = getInfo(User.class); System.out.println(info); }}Copy the code

After the main method runs, you can see the data passed in when the annotation was used in the console. The above is a simple annotation demo, of course, in the actual work will be relatively complex, which requires us to encapsulate and use custom annotations according to the business requirements and code requirements.