10. 注解

一、注解概述

  Annotation其实就是代码里的特殊标记们这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过使用Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署;
  Annotation可以像修饰符一样被使用,可用于修饰类,构造器,方法,成员变量,参数,局部变量的声明,这些信息被保存在Annotation的"name=value"对中;

二、常见的Annotation示例

2.1、生成帮助文档的注解

2.2、在编译时进行格式检查(JDK内置的三个基本注解)

  • @Override:限制重写父类方法,该注解只能用于方法
  • @Deprecated:用于表示所修饰的元素(类,方法等)已过时。通常时因为所修饰的结构危险或存在更好的选择
  • @SupperssWarnings:抑制编译器警告

2.3、跟踪代码依赖性,实现替代配置文件功能

三、自定义注解

  • 自定义新的Annotation类型使用@interface关键字
  • 自定义注解自动继承了java.lang.annotation.Annotation接口
  • Annotation的成员变量在Annotation定义中yi无参数方法的形式来声明。其中方法名和返回值定义了该成员的名字和类型。我们称为配置参数。类型只能时八种基本数据类型、String类型、Class类型、enum类型、Annotation类型、以上所有类型的数组
  • 可以在定义Annotaion的成员变量时为其指定初始值,指定成员变量的初始值可以使用default关键字
  • 如果只有一个参数成员,建议使用参数名为value
  • 如果定义注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。格式是"参数名=参数值",如果只有一个成员参数,且名称为value,可以省略"value="
  • 没有成员定义的Annotation称为标记,包含成员变量的Annotation称为元数组Annotation
public @interface MyAnnotation {
    String value() default "Sakura";
}

@MyAnnotation("Mikoto")
public 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("人吃饭");
    }
}

四、JDK中的元注解

  JDK的元注解用于修饰其它Annotation,JDK 5.0 提供了4个标准的meta-annotation,分别是

  • Retention:用于指定该Annotation的声明周期,@Retention包含一个RetentionPolicy类型的变量,使用@Retention时必须为该value成员变量指定值:
    • RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释
    • RetentionPolicy.CLASS:在class文件中有效(即class保留),当运行Java程序时,JVM不会保留注解。这是默认值
    • RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行Java程序时,JVM会保留注释。程序可以通过反射获取该注解
  • Target:用于指定被修饰Annotation能用于修饰哪些程序元素,@Target包含一个名为value的成员变量
    • CONSTRUCTOR:用于描述构造器
    • FIELD:用于描述域
    • LOCAL_VARIABLE:用于描述局部变量
    • METHID:用于描述方法
    • PACKAGE:用于描述包
    • PARAMETER:用于描述参数
    • TYPE:用于描述类、接口(包括注解类型)或enum声明
  • Documented:用于指定被修饰的Annotation类将被javadoc工具提取成文档。默认情况下,javadoc是不包含注解的
    • 定义为Documented的注解必须设置Retention值为RUNTIME
  • Inherited:被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解

五、JDK 8 中注解的新特性

5.1、可重复注解

5.1.1、JDK 8.0 之前

public @interface MyAnnotations {
    MyAnnotation[] value();
}
public @interface MyAnnotation {
    String value() default "Sakura";
}
@MyAnnotations({@MyAnnotation("Kagome"),@MyAnnotation("Kikyo")})
public 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("人吃饭");
    }
}

5.1.1、JDK 8.0 之后

  1. 在自定义注解MyAnnotation上声明@Repeatable,成员值为MyAnnotation.class
  2. MyAnnotation的Target和Retention、Target、Inherited等元注解与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();
}
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

@Inherited
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
public @interface MyAnnotation {
    String value() default "Sakura";
}
@MyAnnotation("Kagome")
@MyAnnotation("Kikyo")
public 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("人吃饭");
    }
}

5.2、类型注解

  • ElementType.TYPE_PARAMETER:表示该注解能写在类型变量的声明语句中
  • ElementType.TYPE_USE:表示该注解能写在使用类型的任何语句中
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Target;

@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,TYPE_PARAMETER,TYPE_USE})
public @interface MyAnnotation {
    String value() default "Sakura";
}
import java.util.ArrayList;

public class Generic<@MyAnnotation T> {
    
    public void show() throws @MyAnnotation RuntimeException{
        ArrayList<@MyAnnotation String> list = new ArrayList<>();
        int num = (@MyAnnotation int)10L;
    }
}
上一篇:dubbo 的三种用法


下一篇:[Flutter-34] Flutter Json Model