美文网首页
java注解——注解详解和自定义注解

java注解——注解详解和自定义注解

作者: 明丶夷 | 来源:发表于2018-12-17 18:57 被阅读0次

    在上一篇文章中,我们介绍了注解(Annotation)的相关概念,对于 java1.5 引入的这种新特性,我们可以称其为一种特殊的注释。之所以说它特殊是因为不同于普通注释(comment)只能存在于源码,而且还能在程序的编译期跟运行期中存在,会最终编译成一个.class文件。理所应当,注解会比普通注解起到更多的作用。
    注解为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻方便地使用这些数据(通过 解析注解 来使用这些数据)。要想深入的理解并使用注解,必须能定义自己的注解,所以了解java提供的注解定义语法就非常重要了。
    java.lang.annotation中包含所有定义自定义注解所需用到的元注解接口。比如接口java.lang.annotation.Annotation是所有注解都继承的接口,并且是自动继承,不需要定义时指定,类似于所有类都自动继承Object。首先我们先来了解什么是元注解


    元注解

    元注解是 Java 本身提供,是专门用来定义注解的注解。被用来提供对其他注解类型作说明。Java提供了四个标准的元注解类型:

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

    @Target标识 Annotation 可以被使用在什么地方。
    使用方式:@Target(ElementType.METHOD)。其可能的 ElementType 取值包括:

    • CONSTRUCTOR --> 构造器(构造函数)的声明
    • FIELD ---> 域声明,包括 ENUM(枚举)实例
    • LOCAL_VIRIEBLE ---> 局部变量声明
    • METHOD ---> 方法声明
    • PACKAGE ---> 包声明
    • PARAMETER ---> 参数声明
    • *TYPE ---> 类,接口声明。包括注解类型和ENUM类型
    @Retention

    决定了 Annotation 的生命周期,即被保留的时间长短或者说在什么范围内有效。Annotation 一共有三种生命周期,有的注解只出现在源代码中;有的注解被被编译在class文件中,但被虚拟机忽略;有的则是被虚拟机加载,一直到程序运行都还存在。
    使用方式:@Retention(RetentionPolicy = RUNTIME)。其可能的 **RetentionPolicy ** 取值包括:

    • SOURCE -> 在源文件中有效(即源文件保留)
    • CLASS -> 在class文件中有效(即class保留)
    • RUNTIME -> 在运行时有效(即运行时保留)
    @Documented

    描述 Annotation 应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。被例如javadoc此类的工具文档。

    @Inherited

    这也是一个标记注解。@Inherited 阐述了某个被标注的类型是被继承的。被标注过的 class 的子类所继承。类并不从它所实现的接口继承 Annotation,方法并不从它所重载的方法继承 Annotation。
    当使用@Inherited类型标注的 Annotation 的 Retention 是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。


    在本文的开头我们就说过,定义注解时会自动继承java.lang.annotation.Annotation接口。同时还要注意的是,在定义注解时不能继承其他注解和接口
    注解的定义相对简单,有点类似于定义接口:

    public @interface TestAnnotation {
          String field1() default "it's empty"; //default 设置默认值
    }
    

    其中的每个方法都相当于声明了一个配置参数,参数的名称就是方法名,参数的类型就是返回值类型。在自定义注解时有一些注意事项:

    1. 方法(配置参数)只能用 public 或者 默认(default)这两种访问权限修饰。
    2. 方法(配置参数)的返回值支持类型只包括以下几种:
      • 所有的数据类型(int,float,boolean,byte,double,char,long,short
      • String类型
      • Class类型
      • enum类型
      • Annotation(注解)类型
      • 以上所有类型的数组
    3. 注解中有一个特殊的存在:value。当注解中只有一个方法(配置参数)时,最好是将方法命名为 value。这样在使用注解时,就可以省略参数名,比如之后的例子:@Owner
    简单的自定义注解使用例子
    /**
    * book相关的注解。
    * 包括两个参数:名称和页数
    **/
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface BookInfo {
          public String name() default "";
          public int pageSize() default 0;
    }
    
    /**
    * 拥有人注解
    * 只有一个参数,命名为 value
    **/
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Owner {
          public String value() default "";
    }
    
    public class UserBook {
          @BookInfo(name = "EngLish", pageSize = 80)
          public EngLish engLish;
    
          @Owner("testName")
          public String ownerName;
    }
    

    注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。
    在注解的语法部分中,对于特殊的 value 参数,当只指定该参数时,可以省略参数名和等号。这也是上面说的注意事项中第三点的原因

    根据注解参数的不同,可以将注解分为以下几类:

    • 标注注解。没有参数成员,通过判断该注解是否存在获得相关的信息
    • 单值注解。只有一个参数成员,一般为 value,这样可以省略参数名和等号
    • 完整注解

    相关文章

      网友评论

          本文标题:java注解——注解详解和自定义注解

          本文链接:https://www.haomeiwen.com/subject/imumhqtx.html