Java 5 will be able to embed supplementary information in the source code, called annotations, such as the @override Annotation used in method Override, which begins with the **@ symbol.

Annotations do not change the results of application execution and do not affect the performance of application execution. Some annotations give the user hints or warnings at compile time, while others read and write bytecode file information at run time.

Five basic notes

Any annotation is essentially a data type, an interface type. As of Java 8, Java SE provides 11 built-in annotations. Five of these are basic annotations that come from the java.lang package. There are six Meta annotations that come from the java.lang. annotations package and are used for custom annotations.

Meta-annotations are responsible for annotating other annotations.

Basic annotations include: @Override, @Deprecated, @SuppressWarnings, @Safevarargs, and @FunctionalInterface. Let’s take a look at each of them.

@Override can only be used for methods, and a subclass can Override a method of its parent class (or a method that implements an interface) with the @Override annotation. The compiler checks a method annotated by @Override to make sure that the method’s parent class exists, or it will get a compilation error.

package java.lang;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
Copy the code

Deprecated is used to indicate that the API is obsolete

package java.lang;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
Copy the code

SuppressWarnings @suppressWarnings is used to suppress compiler warnings. If you are sure that the warnings in your program are ok, you can ignore them. If you don’t want to see these warnings, you can remove them using the @SuppressWarnings annotation.

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
}
Copy the code

SafeVarargs For example passing mutable parameters, which are non-generic collections

     public class HelloWorld {

         public static void main(String[] args) {
             // Pass mutable arguments, which are generic collections
             display(10.20.30);                            
             // Pass mutable arguments, which are non-generic collections
             display("10".20.30);// there will be a compile warning

         }

         public static <T> void display(T... array) {3.for (T arg : array) {
                 System.out.println(arg.getClass().getName() + ":"+ arg); }}}Copy the code

Add the @safevarargs annotation before the variable display argument. Of course you can also use the @SuppressWarnings(“unchecked”) annotation, but the @Safevarargs annotation is more appropriate.

         @SafeVarargs
         public static <T> void display(T... array) {
             for (T arg : array) {
                 System.out.println(arg.getClass().getName() + ":"+ arg); }}Copy the code
package java.lang;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface SafeVarargs {}
Copy the code

The @functionalinterface annotation was added in Java 8 to declare an interface to be a FunctionalInterface. The @functionalinterface annotation was described in the previous section on Lambda expressions.

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

Six meta-notes

Meta-annotations include: @Documented, @Target, @Retention, @Inherited, @REPEATable, and @native. Meta-annotations are annotations that explain other annotations and can be used when customizing a new annotation type. This section introduces the meanings of these meta-annotations, and the next section details their use in custom annotations.

  1. @Documented

If you reference the @documented annotation in a custom annotation, that annotation modifies code elements (classes, interfaces, member variables, member methods, and so on), and tools like Javadoc can extract the annotation information.

  1. @Target

The @target annotation is used to specify the Target for a new annotation. @ Target annotation has a member (value) is used to set the goal, the value is the Java lang. The annotation. The ElementType enum type of the array, ElementType describe the Java program element type, it has 10 enumerated constants, as shown in table.

  1. @Retention

@ Retention annotation is used to specify a new annotation of effective range, @ Retention annotation has a member (value) is used to set up reserve strategy, the value is the Java lang. The annotation. RetentionPolicy enumerated types, RetentionPolicy describes the annotation RetentionPolicy and has three enumerated constants, as shown in the table.

  1. @Inherited

The @Inherited annotation is used to specify that a new annotation can be Inherited. If A class A is modified by the new annotation, A subclass of class A inherits the new annotation.

  1. @Repeatable

The @REPEATable annotation is a new addition to Java 8 that allows comments to be repeated within the same program element. Repeatable comments must be annotated using @REPEATable.

  1. @Native

Annotate a member variable to indicate that the variable can be referenced by Native code. Often used by code generation tools.

Custom annotations

If the previous 11 built-in annotations provided by Java SE can’t meet your requirements, you can customize annotations, the annotations essence is a kind of interface, it is a Java. Lang. The annotation. The annotation of the interface interface, is the reference data type.

New Annotation Class

Declaring custom annotations can be implemented using the @interface keyword. Example code for the simplest form of annotations is as follows:

package qy.likai.java;

public @interface MyAnnotation {
}
Copy the code

Note that as with classes, multiple annotations can be declared in a source file, but only one of them is public. The name of the source file is the same as the name of the public access annotation.

Marker annotations do not contain any members. Such annotations are Marked annotations. @Override in basic annotations belongs to Marked annotations. Annotations can contain some members if needed. Example code is as follows:

package qy.likai.java;

public @interface MyAnnotation {

    String value(a);

// Members in annotations can also have default values as shown in the following example:
// int count() default 0;
}
Copy the code

Read runtime annotation information

Annotations are prepared for the tool to read the information. Some tools can read annotation information in source files; Some can read annotation information in bytecode files; Some can read annotation information at run time. However, the code to read the annotation information is the same, the only difference is that custom annotations have a different ** @retention strategy **.

To read the annotation information, we need to reflect the relevant API, and the Class method looks like this:

  • A getAnnotation(ClassAnnotationClass) : Returns annotation if there is an annotation of type annotationClass for this element, null otherwise.
  • Annotation[] getanannotations () : Returns any annotations that exist on this element.
  • Annotation[] getDeclaredanannotations (): Returns any annotations that exist directly on this element. The difference with getanannotations () is that this method returns no inherited annotations.
  • boolean isAnnotationPresent(Class
    annotationClass) : Returns true if an Annotation of type annotationClass exists on this element, false otherwise.
  • Boolean isAnnotation() : Returns true if this Class object represents an annotation type.
package qy.likai.java;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

@MyAnnotation("type")
public class AnnotationTest {
    @MyAnnotation("field")
    private String title;

    private String subtitle;

    @MyAnnotation("constructor")
    private AnnotationTest(a){}

    public AnnotationTest(String title) {
        this.title = title;
    }

    public static void main(@MyAnnotation("parameter") String[] args) {
        testAnnotation();
    }

    private static void testAnnotation(a) {
        @MyAnnotation("localVariable")
        String str = "hello MyAnnotation";

        // Read class annotations
        final Annotation[] annotations = AnnotationTest.class.getAnnotations();
        if (AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)) {
            MyAnnotation ann = AnnotationTest.class.getAnnotation(MyAnnotation.class);
            System.out.printf("Class %s, read annotation description: %s \n",
                    AnnotationTest.class.getName(), ann.value());
        }

        // Read the annotation information of the member method
        Method[] methods = AnnotationTest.class.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation ann = method.getAnnotation(MyAnnotation.class);
                System.out.printf("Method %s, read the annotation description: %s \n", method.getName(), ann.value()); }}// Read the annotation information of the member variable
        Field[] fields = AnnotationTest.class.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation ann = field.getAnnotation(MyAnnotation.class);
                System.out.printf("Member variable %s, read the annotation description: %s \n", field.getName(), ann.value()); }}}@MyAnnotation(value = "method")
    @Override
    public String toString(a) {
        return super.toString(); }}// Only RUNTIME can read information dynamically. The default level is CLASS
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String value(a);
}
Copy the code

Three levels of RetentionPolicy in meta-annotations

Retentionpolicy. SOURCE: Annotations are only kept in the SOURCE file. When Java files are compiled into class files, annotations are discarded. Retentionpolicy. CLASS: Annotations are kept in the CLASS file, but are discarded when the JVM loads the CLASS file, which is the default lifecycle. Retentionpolicy. RUNTIME: Annotations are not only saved to the class file, but still exist after the JVM loads the class file.

The three life cycles correspond to: Java source files (.java files) –>.class files –> bytecode in memory.

So how do you choose the right annotation life cycle?

SOURCE < CLASS < RUNTIME = SOURCE < CLASS < RUNTIME = SOURCE < CLASS < RUNTIME Generally, if you need to dynamically retrieve annotation information at RUNTIME, you can only use RUNTIME annotations. 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.

Download the source code

Gitee.com/kaiLee/java…

reference

  • Java from White to big – Seiko Kanto – Chapter 27 Annotations – The Turing Community

www.ituring.com.cn/book/tupuba…

  • RUNTIME annotations for custom annotations (retentionPolicy.runtime)Rukey7’s blog -CSDN blog@retention(retentionpolicy.runtime)

Blog.csdn.net/github_3518…