[Java Basics Series Tutorial] Chapter 17 Java Annotations

1. Annotation overview

        Starting from JDK 5.0, Java has added support for metadata (MetaData), that is, Annotation (annotation).
    
        Annotation is actually a special mark in the code, these marks can be read during compilation, class loading, and runtime, and perform corresponding processing. By using Annotation, programmers can embed some supplementary information in source files without changing the original logic. Code analysis tools, development tools, and deployment tools can be verified or deployed with this supplementary information.
    
        Annotation can be used like a modifier, and can be used to modify packages, classes, constructors, methods, member variables, parameters, and declarations of local variables. These information are stored in the "name=value" pair of Annotation.

        In JavaSE, the purpose of using annotations is relatively simple, such as marking obsolete functions, ignoring warnings, etc. Annotations play a more important role in JavaEE/Android, for example: used to configure any aspect of the application, replacing the cumbersome code and XML configuration left in the old version of JavaEE.

        Future development models are based on annotations, JPA is based on annotations, Spring 2.5 and above are based on annotations, Hibernate3. The trend, to a certain extent, can be said: framework = annotation + reflection + design pattern.

Two, common Annotation examples

        When using Annotation, add the @ symbol in front of it, and use the Annotation as a modifier. Used to decorate the program elements it supports.

Example 1: Generate documentation-related annotations

        @author indicates the author who developed this type of module, and it is used and divided between multiple authors;
        @version indicates the version of this type of module;
        @see refers to the reference, that is, the relevant topic;
        @since is added from which version;
        @param is right The description of a parameter in the method cannot be written if there is no parameter;
        @return The description of the return value of the method cannot be written if the return value type of the method is void;
        @exception The exception that the method may throw, if the method does not Exceptions explicitly thrown by throws cannot be written;
    
among them:
        @param @return and @exception These three tags are only used for methods;
        @param format requirements: @param formal parameter name formal parameter type formal parameter description ;
        Format requirements of @return: @return return value type return value description;
        @exception format requirements: @exception exception type exception description;
        @param and @exception can be used in parallel;

/**
 * @author jimbo
 * @version 1.0
 */
public class JavadocTest {
    /**
     * 程序的主方法,程序的入口
     *
     * @param args String[] 命令行参数
     */
    public static void main(String[] args) {
    }

    /**
     * 求圆面积的方法
     *
     * @param radius double 半径值
     * @return double 圆的面积
     */
    public static double getArea(double radius) {
        return Math.PI * radius * radius;
    }
}

Example 2: Format check at compile time (three basic annotations built into JDK)

        @Override: Restricted to rewrite the parent class method, this annotation can only be used for methods;
    
        @Deprecated: Used to indicate that the modified element (class, method, etc.) is outdated. Usually because the decorated structure is dangerous or there are better options;
    
        @SuppressWarnings: suppress compiler warnings;

public class AnnotationTest {
    public static void main(String[] args) {
        @SuppressWarnings("unused")
        int a = 10;
        
        @SuppressWarnings({ "unused", "rawtypes" })
        ArrayList list = new ArrayList();
    }

    @Deprecated
    public void print() {
        System.out.println("过时的方法");
    }

    @Override
    public String toString() {
        return "重写的toString方法()";
    }
}

Example Three: Tracking Code Dependencies and Implementing Alternative Configuration File Functions

        Servlet3.0 provides annotations, which make it no longer necessary to deploy Servlets in the web.xml file.

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
        ServletException, IOException { }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
        ServletException, IOException {
        doGet(request, response);
    } 
}
<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

        The management of "transactions" in the spring framework.

@Transactional(propagation=Propagation.REQUIRES_NEW,
               isolation=Isolation.READ_COMMITTED,readOnly=false,timeout=3)
public void buyBook(String username, String isbn) {
    //1.查询书的单价
    int price = bookShopDao.findBookPriceByIsbn(isbn);
    //2. 更新库存
    bookShopDao.updateBookStock(isbn);
    //3. 更新用户的余额
    bookShopDao.updateUserAccount(username, price);
}
<!-- 配置事务属性 -->
<tx:advice transaction-manager="dataSourceTransactionManager" id="txAdvice">
    <tx:attributes>
        <!-- 配置每个方法使用的事务属性 -->
        <tx:method name="buyBook" propagation="REQUIRES_NEW"
                   isolation="READ_COMMITTED" read-only="false" timeout="3" />
    </tx:attributes>
</tx:advice>

3. Custom Annotation

        Define a new Annotation type using the @interface keyword;

        Custom annotations automatically inherit the java.lang.annotation.Annotation interface;

        The member variables of Annotation are declared in the form of parameterless methods in the definition of Annotation. Its method name and return value define the name and type of the member. We call them configuration parameters. The type can only be eight basic data types, String type, Class type, enum type, Annotation type, and arrays of all types.

        The initial value can be specified when defining the member variable of Annotation, and the default keyword can be used to specify the initial value of the member variable;

        If there is only one parameter member, it is recommended to use the parameter name value;

        If the defined annotation contains configuration parameters, the parameter value must be specified when using it, unless it has a default value. The format is "parameter name = parameter value". If there is only one parameter member and the name is value, "value=" can be omitted;

        Annotation without member definition is called tag; Annotation containing member variables is called metadata Annotation;

        Note:
                Custom annotations must be accompanied by annotated information processing flow (using reflection) to make sense.
                Custom annotations usually specify two meta-annotations: Retention and Target.

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface MyAnnotation {
    String value() default "hello";
}

// 如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。
// @MyAnnotation(value = "hi")
@MyAnnotation
class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void walk() {
        System.out.println("人走路");
    }

    public void eat() {
        System.out.println("人吃饭");
    }
}

4. Meta annotations in JDK

        JDK's meta-Annotation is used to modify other Annotation definitions;

        JDK5.0 provides four standard meta-annotation types, namely:
                Retention
                Target
                Documented
                Inherited

4.1 @Retention meta-annotation

        @Retention: Can only be used to modify an Annotation definition to specify the life cycle of the Annotation. @Rention contains a member variable of type RetentionPolicy. When using @Rention, you must specify a value for the value member variable: RetentionPolicy.SOURCE: In the
                source Valid in the file (that is, the source file is retained), the compiler directly discards the comments of this policy;
                RetentionPolicy.CLASS: Valid in the class file (that is, the class is retained), when running the Java program, the JVM will not retain the annotation. This is the default value;
                RetentionPolicy.RUNTIME: Effective at runtime (that is, retained at runtime), when running a Java program, the JVM will retain the annotation. Programs can obtain this annotation through reflection.

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     * 编译器将丢弃注解。
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     * 注解将由编译器记录在类文件中但不需要在运行时由VM保留。这是默认设置行为
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     * 
     * @see java.lang.reflect.AnnotatedElement
     * 注解将由编译器记录在类文件中,并且由VM在运行时保留,因此可以反射地读取它们。
     */
    RUNTIME
}

@Retention(RetentionPolicy.SOURCE)
@interface MyAnnotation1{ }

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{ }

4.2 @Target meta-annotation

        @Target: It is used to modify the definition of Annotation, which is used to specify which program elements the modified Annotation can be used to modify. @Target also contains a member variable named value.

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    // 类、接口(包括注解类型)或枚举声明
    TYPE,

    /** Field declaration (includes enum constants) */
    // 字段声明(包括枚举常量)
    FIELD,

    /** Method declaration */
    // 方法声明
    METHOD,

    /** Formal parameter declaration */
    // 形式参数声明
    PARAMETER,

    /** Constructor declaration */
    // 构造函数声明
    CONSTRUCTOR,

    /** Local variable declaration */
    // 局部变量声明
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    // 注解类型声明
    ANNOTATION_TYPE,

    /** Package declaration */
    // 包声明
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

// 我们移除MyAnnotation @Target中的TYPE,如果再在类上定义该注解,则报错
@Target({FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER, TYPE_USE})
public @interface MyAnnotation {
    String value() default "hello";
}


// 报错信息:'@MyAnnotation' not applicable to type

4.3 @Documented meta-annotation

        @Documented: It is used to specify that the Annotation class modified by the meta-Annotation will be extracted into a document by the javadoc tool. By default, javadoc does not include annotations.
        Annotations defined as Documented must set the Retention value to RUNTIME.

        Note: See Date API for details;

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

4.4 @Inherited meta-annotation

        @Inherited: Annotation modified by it will have inheritance. If a class uses Annotation modified by @Inherited, its subclasses will automatically have the annotation.
                For example: If a custom annotation marked with the @Inherited annotation is marked at the class level, the subclass can inherit the class-level annotation of the parent class.
                In practical applications, it is less used.

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface MyAnnotation {
    String value() default "hello";
}
@MyAnnotation(value="hi")
class Person{
    private String name;
    private int age;

    public Person() {
    }
    @MyAnnotation
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @MyAnnotation
    public void walk(){
        System.out.println("人走路");
    }
    public void eat(){
        System.out.println("人吃饭");
    }
}

class Student extends Person{

}

class Test{
    public static void main(String[] args) {
        // 利用反射测试子类是否继承父类的注解
        Class clazz = Student.class;
        Annotation[] annotations = clazz.getAnnotations();
        for(int i = 0;i < annotations.length;i++){
            System.out.println(annotations[i]);
        }
    }
}

5. Use reflection to obtain annotation information

        JDK 5.0 adds the AnnotatedElement interface under the java.lang.reflect package, which represents the program elements that can accept annotations in the program.
    
        When an Annotation type is defined as runtime Annotation, the annotation will be visible at runtime, and the Annotation saved in the class file will be read by the virtual machine when the class file is loaded.
    
        The program can call the following methods of the AnnotatedElement object to access the Annotation information.

        Note: Reflection explanation in the next chapter;

6. New features of annotations in JDK8

 6.1 Repeatable annotations

Duplicate annotations were implemented before JDK8:

        If we define two annotations repeatedly, the following error will be reported:
                Duplicate annotation. The declaration of 'MyAnnotation' does not have a valid java.lang.annotation.Repeatable annotation

        Before JDK8, it had to be implemented with the help of another annotation class.

public @interface MyAnnotations {
    MyAnnotation[] value();
}

@MyAnnotations({@MyAnnotation(value="hi"),@MyAnnotation(value="hello")})
class Person{}

An example of repeatable annotations after JDK8:

        Note:
                Declare @Repeatable on MyAnnotation, and the member value is MyAnnotations.class;
                the meta-annotations such as Target and Retention of MyAnnotation are the same as MyAnnotations.

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface MyAnnotations {
    MyAnnotation[] value();
}


@Inherited
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface MyAnnotation {
    String value() default "hello";
}

@MyAnnotation(value="hi")
@MyAnnotation(value="abc")
class Person{}

6.2 Type annotations

        After JDK1.8, there are two more ElementType enumeration values ​​for the parameter type of the meta-annotation @Target: TYPE_PARAMETER, TYPE_USE.

        Before Java 8, annotations could only be used where they were declared. Starting with Java 8, annotations can be applied anywhere.
                ElementType.TYPE_PARAMETER indicates that the annotation can be written in the declaration statement of the type variable (eg: generic declaration).
                ElementType.TYPE_USE indicates that the annotation can be written in any statement that uses the type.

@Inherited
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER,TYPE_USE})
public @interface MyAnnotation {

    String value() default "hello";
}

public class Generic<@MyAnnotation T>{

    public void show() throws @MyAnnotation RuntimeException{

        ArrayList<@MyAnnotation String> list = new ArrayList<>();

        int num = (@MyAnnotation int) 10L;
    }

}

7. Interview questions

1. Understand the enumeration class?
    There are only a limited number of objects in the class, which is definite.
    When you need to define a set of constants, it is strongly recommended to use an enumeration class.
    If the enumeration has only one object, it can be used as an implementation of the singleton pattern.

2. How to create an enumeration class?
    Before JDK1.5, you need to customize the enumeration class;
    the new enum keyword in JDK1.5 is used to define the enumeration class;

3. Features of the enumeration class?
    1. The constructor of the privatized class ensures that its objects cannot be created outside the class;
    2. An instance of the enumeration class is created inside the class. Declared as: public static final;
    3. If the object has an instance variable, it should be declared as private final and initialized in the constructor;
    Note: The enumeration class declared by enum and the enumeration class declared by class are basically similar, except that the declaration Concise syntax for enum class objects;

4. What is the role of the enum keyword?
    First, the enum declaration actually defines a class. So we can call its methods through the defined enum.
    Secondly, the Java compiler will automatically insert some methods into the enum type, including values()-so when our program is not compiled, naturally we cannot view the source code of the values() method.

5. Use the enumeration class defined by the enum keyword to implement the interface?
    If each enumeration value exhibits the same behavior when calling the implemented interface method, then it is only necessary to implement the method uniformly.
    If it is required that each enumeration value exhibits different behaviors when calling the implemented interface method, each enumeration value can implement the method separately.

6. What is an annotation? And its function?
    Starting from JDK 5.0, Java has added support for metadata (MetaData), which is Annotation (annotation).
    Annotation is actually a special mark in the code, these marks can be read during compilation, class loading, and runtime, and perform corresponding processing.
    Annotation can be used like a modifier, and can be used to modify packages, classes, constructors, methods, member variables, parameters, and declarations of local variables. These information are stored in the "name=value" pair of Annotation.

7. Commonly used annotations in JAVASE?
    @Override: Limit rewriting parent class methods, this annotation can only be used for methods; check whether it is an overridden method at compile time;
    @Deprecated: Used to indicate the modified element (class, method etc.) are obsolete. Usually because the modified structure is dangerous or there are better choices;
    @SuppressWarnings: suppress compiler warnings;
    
8. How to customize annotations?
    1. Define a new Annotation type using the @interface keyword, and custom annotations automatically inherit java .lang.annotation.Annotation interface.
    2. The member variables of Annotation are declared in the form of a parameterless method in the definition of Annotation. Its method name and return value define the name and type of the member. We call them configuration parameters. The type can only be eight basic data types, String type, Class type, enum type, Annotation type, and arrays of all types.
    3. If there is a member variable in our custom annotation, it must be assigned a value when using it; if the member variable of the custom annotation is assigned a default value, then we can assign a value or not assign a value when we use it; we
        need default to assign values ​​to the member variables of the annotation
    4. If there is only one parameter member, it is recommended to use the parameter name value;
    5. Annotation without member definitions is called a tag; Annotation containing member variables is called metadata Annotation;
        we can all call it for annotation;

9. What are meta-annotations, what are the meta-annotations, and what are their functions?
    JDK’s meta-Annotation is used to modify other Annotation definitions;
    @Retention: can only be used to modify an Annotation definition, and is used to specify the life cycle of the Annotation. @Rention contains A member variable of RetentionPolicy type, when using @Rention, you must specify a value for the value member variable:
        RetentionPolicy.SOURCE: valid in the source file (that is, the source file is retained), and the compiler directly discards the comments of this policy;
        RetentionPolicy.CLASS: Valid in class files (that is, class retention), when running Java programs, JVM will not retain annotations. This is the default value;
        RetentionPolicy.RUNTIME: Effective at runtime (that is, retained at runtime), when running a Java program, the JVM will retain the annotation. Programs can obtain this annotation through reflection.
    @Target: It is used to modify the definition of Annotation, which is used to specify which program elements the modified Annotation can be used to modify. @Target also contains a member variable named value.
    @Documented: Used to specify that the Annotation class modified by the meta-Annotation will be extracted into a document by the javadoc tool. By default, javadoc does not include annotations.
    @Inherited: Annotation modified by it will have inheritance.

10. New features of JDK8 annotations?
    Java 8 provides two improvements to annotation processing: repeatable annotations and annotations that can be used for types.

11. Implementation of repeated annotations?
    Before jdk8:
        If you want to implement repeated annotations before jdk8, such as the annotation MyAnnotation wants to be defined repeatedly; then define a MyAnnotations annotation; the
        member variable type in MyAnnotations is MyAnnotation[] value();
        Use of annotations: @MyAnnotations({@MyAnnotation(value = "myAnnotation"),@MyAnnotation})
    After jdk8:
        If you want to implement repeated annotations after jdk8, the first two steps are the same;
        declare @Repeatable on MyAnnotation, and the member value is MyAnnotations.class;
        Meta-annotations such as Target and Retention of MyAnnotation are the same as MyAnnotations.

Guess you like

Origin blog.csdn.net/ligonglanyuan/article/details/123373183