JDK的元注解

元注解,英文名称Meta Annotation,是作用于注解的注解。换言之,元注解是用于声明,创建注解的时候用到的标记,符号。Jdk 在java.lang包下提供了五个基本注解(基本注解章节的五个注解)的同时,又在java.lang.annotation包下提供了六个元注解。这个六个元注解中只有五个元注解可以用于修饰其它注解,较为特殊的一个则是Java 8新增的重复注解。

这六个元注解分别是

  1. @Retention
  2. @Target
  3. @Documented
  4. @Inherited
  5. @Repeatable

@Retention

设想一下,你要创建一个注解给其它开发者使用。正如你创建一个类给其它开发者使用一样,你必须指定该类的某些规则,比如指定该类只能连接MySQL数据库。注解也一样,在创建的时候需要指定该注解的某些规则,比如可以保留多长时间。

 

@Retention注解就是在声明创建一个注解的时候,指定这个被声明创建的注解可以保留多长时间。它里边有一个RetentionPolicy类型的value变量,该变量的值只有三个,不同的值代表不同的保留规则。

 

具体保留规则如下:

  1. RetentionPolicy.CLASS

编译器将注解记录在.class文件中。当运行Java程序时,JVM不能获取注解信息。这是默认值

  1. RetentionPolicy.RUNTIME

编译器将注解记录在.class文件中。当运行Java程序时,JVM也能获取注解信息。程序可以通过反射获取注解信息。

  1. RetentionPolicy.SOURCE

编译器直接丢弃注解。所以该注解只能保留在源代码文件中。

注意,使用@Retention注解必须为value变量赋值。

 

示例代码

 

//创建声明Test注解,该注解被使用的时候只能可以保留到运行阶段

@Retention(value = RetentionPolicy.RUNTIME)

public @interface Test {}

//创建声明Test注解,该注解编译器将直接丢弃,所以只能保留在源代码中

@Retention(RetentionPolicy.SOURCE)

public @interface Test{}

 

总结 :     声明创建注解要使用@interface这种格式

使用注解的时候,如果只需要给注解的value属性赋值,直接将value属性的值写出即可,无需再使用key=value形式。

@Target

@Target注解是在声明创建一个注解的时候,指示该注解可以作用于程序中的哪些元素。它里边也包含一个名为value的成员变量,value成员变量的值有如下几种

 

  1. ElementType.ANNOTATION_TYPE指定当前注解只能修饰其它注解
  2. ElementType.CONSTRUCTOR指定当前注解只能修饰构造方法
  3. ElementType.FIELD指定当前注解只能修饰成员变量
  4. ElementType.LOCAL_VARIABLE指定当前注解只能修饰局部变量
  5. ElementType.METHOD指定当前注解只能修饰方法
  6. ElementType.PACKAGE指定当前注解只能修饰包
  7. ElementType.PARAMETER指定当前注解只能修饰参数
  8. ElementType.TYPE指定当前注解可以修饰类,接口,其它注解,枚举等类型

 

示例代码

 

//创建声明Test注解,该注解只能修饰成员变量

@Target(ElementType.FIELD)

public @interface Test {}

//创建声明Test注解,该注解只能修饰方法

@Target(ElementType.METHOD)

public @interface Test {}

 

@Documented

@Documented元注解是在声明创建一个注解的时候,指示该注解将被javadoc工具提取成文档。这样所有使用该注解的程序元素的API文档中都会包含该注解说明。

 

示例代码

 

声明一个使用@Documented注解的注解

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Documented

public @interface MyDocument {}

 

声明一个测试类,该类使用了@MyDocument注解

public class TestDocument {

    @MyDocument

    public void test() {}

}

 

效果图

可以看到,javadoc提取TestDocument.java成API文档的时候,将注解@MyDocument的说明信息也提取到了文档中。

@Inherited

@Inherited注解是在声明创建一个注解的时候,指定该注解将具有继承性:如果某个类使用了该注解,则其子类也将自动被改注解所修饰。

 

示例代码

声明创建一个注解

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Inherited

public @interface MyInherited {}

 

创建一个父类

@MyInherited

public class MyInheritedTestFu {}

所有的子类都将自动将@MyInherited注解给继承

 

创建子类进行测试

public class MyInheritedTestZi extends MyInheritedTestFu {

    public static void main(String[] args) {

        boolean a = MyInheritedTestZi.class.isAnnotationPresent(MyInherited.class);

        System.out.println(a);

    }

}

打印结果为true,可以看到虽然子类没有使用@MyInherited注解,却依然是被@MyInherited注解所修饰。如果将@MyInherited

的@Inherited元注解去掉,那么子类将无法从父类继承@MyInherited注解。打印结果将会是false.

@Repeatable

某些情况下,一个程序元素需要使用多个同一种类型的注解。@Repeatable元注解,顾名思义,重复注解,就是在声明创建注解的时候,指定该注解可以被同一个程序元素多次使用。

例如一个公司的创始人,它既是CEO,又是产品经理,还要负责财务,招聘等等,具有多种角色身份。这种情况就可以使用重复注解。

 

示例代码

 

声明注解和注解容器

/* 声明注解,该注解可以被程序元素重复使用 */

@Repeatable(Roles.class)

public @interface Role {

    String value();

}

/* 定义注解"容器" : Roles里边是Role的数组,这样Roles里边就可以存放多个Role */

public @interface Roles {

    Role[] value();

}

使用重复注解

@Role("CEO")

@Role("UFO")

public class People { }

 

注意

  1. “容器”注解Roles的保留期必须比它所包含的注解Role的保留期更长,否则编译器会报错。
  2. 重复注解是Java 8新增的元注解
  3. Java 8以前不允许重复注解,所以之前都只能用如下形式来表达

//直接使用Roles来盛装Role

@Roles({ @Role("CEO"), @Role("UFO") })

public class People {}

  1. 重复注解不是一个语言上的改变,只是编译器层面的改动,技术层面仍然是一样的。其本质依然是多个重复注解作为了“容器”注解的value成员变量的数组元素。本质代码请看注意3

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的王小卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值