[Java Advanced] Reflection Learning One-Annotation

Java Annotation Type (@Annotation)

Java annotations are a new feature introduced in JDK5. Given that most of the current frameworks (such as Spring) use annotations to simplify the code and improve coding efficiency, it is necessary for a Java engineer to master and understand annotations. .

1. Understand Java annotations

In fact, pubic, static voidthere is not much difference between the use of Java annotations and ordinary modifiers ( etc.). The following examples are common annotations:

/**
 * @author zn
 * @date 2020/3/30
 **/
public interface Animal {
    void eat();
}

/**
 * @author zn
 * @date 2020/3/30
 **/
public class Dog implements Animal {
    
    @Deprecated
    @Override
    public void eat() {
        
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
    }
}

Of course, we have already seen the @Testannotation. This annotation does not indicate that it is a unit test and can be executed directly.

In this example, @Deprecated means that this method is outdated. The next version may be abolished. @Override means that this method is inherited or implemented. If the method name is written incorrectly, an error will be reported.

Annotations can be reclassed or inside

For @Deprecatedsum @SuppressWarnings("uncheck"), it is a built-in annotation in Java itself, which can often be seen in the code, but this is not a good thing. After all, when a method or class has an @Deprectedannotation, it means that the method or class has expired and is not It is recommended to use, @SuppressWarningswhich means to ignore the specified warning. For example @SuppressWarnings("uncheck"), this is the simplest way to use annotations. Let's take a look at the basic syntax of annotation definitions.

2. Basic Grammar

(1) Statement annotations and meta annotations

Let's take a look at how the previous Testannotations are declared:

//声明Test注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
    
}

We use a @interfacedeclared Testannotation, and use the @Targetannotation to pass in the ElementType.METHODparameter to indicate that it @Testcan only be used on the method, which @Retention(RetentionPolicy.RUNTIME)is used to indicate that the life of the annotation is runtime. From the code point of view, the definition of the annotation is very similar to the definition of the interface. , After all, Test.classfiles will be generated after compilation . For @Targetsum @Retentionis a meta-annotation provided by Java, the so-called meta-annotation is an annotation that marks other annotations, which are introduced below:

  • @TargetUsed to constrain the places where annotations can be applied (such as methods, classes, or fields), which ElementTypeis an enumeration type, which is defined as follows, and also represents the possible range of values
public enum ElementType{
    //标明该注解可以用于类、接口(包括注解类型)或enum声明
    TYPE,
    
    //标明该注解可以用于字段(域)声明,包括enum实例
    FIELD,
    
    //标明该注解可以用于方法声明
    METHOD,
    
    //标明该注解可以用于参数声明
    PARAMETER,
    
    //标明注解可以用于构造函数声明
    CONSTRUCTOR,
    
    //标明注解可以用于局部变量声明
    LOCAL_VARIABLE,
    
    //标明注解可用于注解声明(应用于另一个注解上)
    ANNOTATION_TYPE,
    
    //标明注解可以用于包声明
    PACKAGE,
    
    /**
    *标明注解可以用于类型参数声明(1.8新加入)
    *@since 1.8
    */
    TYPE_PARAMETER,
    
    /**
    *类型使用声明(1.8新加入)
    *@since1.8
    */
    TYPE_USE
}

Note that when the annotation does not specify a Targetvalue, the annotation can be used on any element, and multiple values ​​are {}included and separated by commas, as follows:

@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
@Retention

Used to constrain the life cycle of annotations, there are three values ​​respectively, source code level

source

, Class file level

class

Or runtime level

runtime

, And its meaning is as follows:

  • SOURCE: Annotation will be discarded by the compiler (this type of annotation information will only be retained in the source code. After the source code is compiled, the annotation information will be discarded and will not be retained in the compiled .classfile)
  • CLASS: Annotation .classis available in the file, but it will be discarded by the JVM (this type of annotation information will be kept in the source code and in the .classfile, and will not be loaded into the virtual machine during execution). Please note that when the annotation has no Retentionvalue defined , The default value is CLASS, such as Java built-in annotations, @Override,@Deprecated,@SuppressWarningetc.
  • RUNTIME: The annotation information will be retained during the runtime (JVM), so the annotation information can be read through the reflection mechanism (the source code, the .classfile, and the execution time have annotation information), such as SpringMVCin @Controller, @Autowired, @RequestMapping.

(2) Annotation elements and their data types

Through the above @Testdefinition of annotations, we understand the process of annotation definition. Since @Testthere are no other elements defined internally, it @Testis also called marker annotation , but in custom annotations, some elements are generally included to represent certain values , To facilitate the use of the processor, this will be seen in the following example:

@Target(ElementType.TYPE)//只能应用于类上
@Retention(RetentionRolicy.RUNTIME)//保存到运行时
public @interface DBTable{
    String name() default "";
}

The above defines an DBTableannotation named , which is mainly used for the mapping of the database table domain Bean class (a complete case analysis will be available later). Unlike the previous Testannotations, we declare a Stringtype of nameelement, and its default value is a null character String, but it must be noted that the declaration corresponding to any element should adopt the method declaration method, and at the same time, you can choose to defaultprovide default values. The @DBTableusage is as follows:

@DBTable(name = "MEMBER")
public class Member{
    //...
}

The element data types supported by annotations are listed above String, and the following data types are also supported:

  • All basic types ( int, float, boolean, byte, double, char, long, short)
  • String
  • Class
  • enum
  • Annotation
  • Array of the above type

If other data types are used, the compiler will throw a compilation error. Note that you can use basic types when declaring annotated elements, but you are not allowed to use any packaging types. At the same time, it should be noted that annotations can also be used as element types. It is nested annotations. The following code demonstrates the use of the above types:

package com.guirunxiang.annotationdemo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Reference{
    boolean next() default false;
}

public @interface AnnotationElementDemo {
    //枚举类型
    enum Status {FIXED, NORMAL};

    //声明枚举
    Status status() default Status.FIXED;

    //布尔类型
    boolean showSupport() default false;

    //String类型
    String name() default "";

    //class类型
    Class<?> testCase() default Void.class;

    //注解嵌套
    Reference reference() default @Reference(next = true);

    //数组类型
    long[] value();
}

(3) Compiler restrictions on default values

The compiler is a bit picky about the default value of the element. First, the element cannot have an indeterminate value. In other words, the element must either have a default value or provide the value of the element when using the annotation. Second, for non-basic types of elements, either in the statement or in the source code annotation interface to define default values are not to nullthe value.

(4) Annotation does not support inheritance

Annotations do not support inheritance, so you cannot use keywords extendsto inherit one @interface, but after the annotation is compiled, the compiler will automatically inherit the java.lang.annotation.Annotationinterface. Here we decompile the DBTableannotation defined earlier :

package com.guirunxiang.annotationdemo;

import java.lang.annotation.Annotation;
//反编译后的代码
public interface DBTable extends Annotation{
    public abstract String name();
}

Although it is found after decompilation that the DBTableannotation inherits the Annotationinterface, extendskeyword inheritance is still not available when defining annotations @interface.

(5) Shortcut

The so-called shortcut is that the named valueelement is defined in the annotation, and when using the annotation, if the element is the only element that needs to be copied, then there is no need to use the key = valuesyntax at this time , and only the valuerequired elements of the element are given in parentheses Value. This can be applied to any legal type of element, but this restricts the element name must be value. A simple case is as follows:

package com.guirunxiang.annotationdemo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//定义注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface IntegerValue{
    int value() default 0;
    String name() default "";
}

//使用注解
public class QuicklyWay {
    
    //当只想给value赋值时,可以使用一下快捷方式
    @IntegerValue(20)
    public int age;
    
    //当name也需要赋值是必须采用key = value的方式赋值
    @IntegerValue(value = 1000, name = "MONEY")
    public int money;
}

3. Java built-in annotations

Then look at the built-in annotations provided by Java, there are mainly three, as follows:

  • @Override: Used to indicate the coverage of this method Fred method, the source code is as follows:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override{
    
}
  • Deprecated: Used to mark obsolete methods or classes, the source code is as follows, about @Documentedlater analysis:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated{
    
}
  • @SuppressWarnnings: Used to selectively turn off the compiler's warnings for classes, methods, member variables, and variable initialization. The source code is as follows:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

There is an Stringarray inside , the main receiving values ​​are as follows:

parameter name Description
"deprecation" Warning when using deprecated classes or methods
"unchecked" A warning when an unchecked conversion is performed, for example, when a collection is used, Generics is not used to specify the type saved by the collection
"fallthrough" When switchone kind of the block direct access to the case without breakwarning of
"path" Warning when there is a path that does not exist in the class path, source file path, etc.
"serial" When the missing of sequence in the class may be serialVersionUIDdefined when the warning
"finally" Any finallywarning clause can not be completed properly
"all" Warning about all the above

These three annotations are relatively simple, let's look at a simple case:

//注明该类已过时,不建议使用
@Deprecated
Class A{
    public void A(){ }
    
    //注明该方法已过时,不建议使用
    @Deprecated
    public void B(){ }
}

class B extends A{
    @Override //标明覆盖父类A的A方法
    public void A(){
        super.A();
    }
    
    //去掉检测警告
    @SuppressWarnings({"uncheck", "deprecation"})
    public void C(){ }
    
    //去掉检测警告
    @SuppressWarnings("uncheck")
    public void D(){ }
}

Earlier we analyzed two kinds of meta-annotations, @Targetand @Retention. In addition to these two kinds of meta-annotations, Java also provides two other kinds of meta-annotations, @Documentedand @Inherited, which are introduced below:

  • @DocumentedModified comments will be generated javadocin
//使用@Documented
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentA {
}

//没有使用@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentB {
}

//使用注解
@DocumentA
@DocumentB
public class DocumentDemo {
    public void A(){
    }
}

Use the javadoccommand to generate documentation:

javadoc DocumentDemo.java DocumentA.java DocumentB.java 

As follows, you can find that the @Documentedannotations defined using meta annotations @DocumentAwill be generated in the javadoc, but @DocumentBnot in the doc document. This is @Documentedthe role of meta annotations .

img

image-20200323120949046.png

  • @InheritedAnnotations can be inherited, but this is not true inheritance, just by using @Inherited, you can let subclass Classobjects use to getAnnotations()get @Inheritedthe annotations modified by the parent class , as follows:
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentA {
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentB {
}

@DocumentA
class A{ }

class B extends A{ }

@DocumentB
class C{ }

class D extends C{ }

//测试
public class DocumentDemo {

    public static void main(String... args){
        A instanceA=new B();
        System.out.println("已使用的@Inherited注解:"+Arrays.toString(instanceA.getClass().getAnnotations()));

        C instanceC = new D();

        System.out.println("没有使用的@Inherited注解:"+Arrays.toString(instanceC.getClass().getAnnotations()));
    }

    /**
     * 运行结果:
     已使用的@Inherited注解:[@com.zejian.annotationdemo.DocumentA()]
     没有使用的@Inherited注解:[]
     */
}

Link: https://www.jianshu.com/p/2f96679ff094

●The strongest Tomcat8 performance optimization in history

Why can Alibaba resist 10 billion in 90 seconds? --The evolution of server-side high-concurrency distributed architecture

B2B e-commerce platform--ChinaPay UnionPay electronic payment function

Learn Zookeeper distributed lock, let interviewers look at you with admiration

SpringCloud e-commerce spike microservice-Redisson distributed lock solution

Check out more good articles, enter the official account--please me--excellent in the past

A deep and soulful public account 0.0

Guess you like

Origin blog.csdn.net/a1036645146/article/details/111031954