可重复注解

jdk8.0中出现了两个关于注解的新特性
  1. 可重复注解
  2. 类型注解
如果我们在实际编程中我们需要添加注解的时候如果同一个结构处我们需要添加两个相同的注解时(但是这个时候这两个注解的配置参数不同),这个时候我们就要使用到可重复注解
  • 但是这个时候又要分为两种情况
1. jkd8.0之前
  • jdk8.0之中才提出了可重复注解,那么在jdk8.0之前我们如何实现这种同一位置使用两个同类型注解的情况
  • 假如这个时候我们自定义的注解是@MyAnnotation,这里我们先给出@MyAnnotation注解的定义:
package 注解.可重复注解;

public @interface MyAnnotation {
    //设置自定义注解的配置参数,默认值为字符串"hello"
    String value() default "hello";
}
  • 这个时候我们要重新创建一个自定义注解类@MyAnnotations
  • 我们这个时候要将新定义的注解类@MyAnnotations的配置参数设置为 MyAnnotation [] 类型的,这个时候我们就可以通过定义一个@MyAnnotations的方式就其实相当于定义了一个MyAnnotation [] ,我们定义的这个MyAnnotation [] 中就可以一次实现多个@MyAnnotation的声明
package 注解.可重复注解;

public @interface MyAnnotations {
    //设置注解的配置参数,没有默认值情况
    MyAnnotation [] value();
}
  • 最后我们如果要声明就要声明为这种形式:
package 注解.可重复注解;
@MyAnnotations({@MyAnnotation("he"),@MyAnnotation("hello")})
public class Demo {
    
}
总结(JDK8.0之前):

我们可以发现在jdk8.0之前我们要在同一位置将同一注解(eg: @MyAnnotation)声明两次其实是通过了数组的方式,将我们要重复定义的注解以数组的形式定义在另一注解(eg: @MyAnnotations)中,这个时候我们定义一个@MyAnnotations注解就相当于定义了一个或者多个@MyAnnotation注解

2. jdk8.0包括之后

而在jdk8.0之后,这个时候我们提出了可重复注解的概念

  • 这个时候我们要提到一个新的元注解: @Repeatable
那么究竟如何定义可重复注解?
  1. 我们要在要定义的可重复注解@MyAnnotation上声明上我们新提到的元注解@Repeatable,并且这个元注解有配置参数,我们要将配置参数设置为: MyAnnotations.calss
  • 那么这里的MyAnnotations.class又是什么?
  • 这个和我们jdk8.0之前一样,@MyAnnotations其实就是我们定义的一个新的注解,这个注解中配置参数为MyAnnotation []类型
  1. 注意修饰我们定义的@MyAnnotation和@MyAnnotations这两个注解的元注解必须全部相同
  • 如果Target或者Retention不相同,这个时候编译就不会通过
  • 如果Inherited不相同,这个时候就会报出一个Error
这类我们就给出jdk8.0之后我们定义的可重复注解的具体代码:
  • 先给出@MyAnnotation
package 注解.可重复注解;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})
@Inherited
@Repeatable(MyAnnotations.class)

public @interface MyAnnotation {
    //设置自定义注解的配置参数,默认值为字符串"hello"
    String value() default "hello";
}
  • 然后我们再给出@MyAnnotations
package 注解.可重复注解;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})
@Inherited

public @interface MyAnnotations {
    //设置注解的配置参数,没有默认值情况
    MyAnnotation [] value();
}
  • 那么这个时候我们如果要声明就直接可以在一个结构处声明两个@MyAnnotation
package 注解.可重复注解;

@MyAnnotation("he")
@MyAnnotation("hello")

public class Demo {

}
补充:

为什么我们修饰我们定义的两个注解@MyAnnotation和@MyAnnotations的元注解都必须要相同?

  • 因为我们在定义MyAnnotation为可重复注解的时候添加了一个元注解@Repeatable(MyAnnotations.class), 也就是这个时候如果我们的@MyAnnotation是通过@Repeatable(MyAnnotations.class)元注解修饰的,而这个元注解中又使用到了MyAnnotations.class,那么这个时候我们可以进行思考:
  • 如果我们定义的MyAnnotation注解的生命周期是"运行时保留",但是声明的MyAnnotations却是"编译时保留",这个时候我们的MyAnnotation注解是要保留到运行时的,但是修饰它的MyAnnotations的声明周期却只有编译时,.这个时候就会矛盾,也就是我们定义的MyAnnotations的生命周期要比MyAnnotation的生命周期更长或者相同,更长没有必要,所以我们就设置为相同,也就是Retention要相同
  • 而对于Target,和Inherited等元注解同理也需要相同