@Repeatable演示(附:注解思维导图)
例1:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(ResourcePaths.class)
public @interface ResourcePath {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResourcePaths {
ResourcePath[] value();
}
@ResourcePath("/file/1")
@ResourcePath("/file/2")
public class RepeatableTest {
}
@ResourcePath("/file/3")
@ResourcePath("/file/4")
public class RepeatableSon extends RepeatableTest {
}
public class Test {
public static void main(String[] args) {
Class clazz = RepeatableSon.class;
//通过getAnnotationsByType方法获取所有重复注解
ResourcePath[] annotationsByType = (ResourcePath[]) clazz.getAnnotationsByType(ResourcePath.class);
ResourcePath[] annotationsByType2 = (ResourcePath[]) clazz.getDeclaredAnnotationsByType(ResourcePath.class);
if (annotationsByType != null) {
for (ResourcePath resourcePath : annotationsByType) {
System.out.println("1:"+resourcePath.value());
}
}
System.out.println("-----------------");
if (annotationsByType2 != null) {
for (ResourcePath resourcePath : annotationsByType2) {
System.out.println("2:"+resourcePath.value());
}
}
System.out.println("-----------------");
System.out.println("使用getAnnotation的结果:"+clazz.getAnnotation(ResourcePath.class));
}
}
输出的结果:
1:/file/3
1:/file/4
-----------------
2:/file/3
2:/file/4
使用getAnnotation的结果:null
通过上面的结果可以看出
使用Repeatable注解的重复注解是无法使用getAnnotation去获取注解信息的。
例2:
public class RepeatableSon2 extends RepeatableTest {
}
public class Test {
public static void main(String[] args) {
//通过getAnnotationsByType方法获取所有重复注解
Class clazz2 = RepeatableSon2.class;
ResourcePath[] annotationsByType3 = (ResourcePath[]) clazz2.getAnnotationsByType(ResourcePath.class);
ResourcePath[] annotationsByType4 = (ResourcePath[]) clazz2.getDeclaredAnnotationsByType(ResourcePath.class);
if (annotationsByType3 != null) {
for (ResourcePath resourcePath : annotationsByType3) {
System.out.println("3:"+resourcePath.value());
}
}
System.out.println("-----------------");
if (annotationsByType4 != null) {
for (ResourcePath resourcePath : annotationsByType4) {
System.out.println("4:"+resourcePath.value());
}
}
System.out.println("使用getAnnotation的结果:"+clazz2.getAnnotation(ResourcePath.class));
}
}
测试结果
-----------------
使用getAnnotation的结果:null
你会发现,并没有输出注解信息。这是因为@ResourcePath注解没有添加@Inherited注解,所以无法查询到注解信息。
例3:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Repeatable(ResourcePaths.class)
public @interface ResourcePath {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ResourcePaths {
ResourcePath[] value();
}
测试结果
3:/file/1
3:/file/2
-----------------
使用getAnnotation的结果:null
我们可以发现可以获取到父类的注解信息了。需要注意的是如果你用例1去添加@Inherited注解的话,依旧无法获取到父类的注解信息。其实我们查看源码会发现。只有子类没有注解的时候才会去获取父类的注解。
default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
//先调用getDeclaredAnnotationsByType方法
T[] result = getDeclaredAnnotationsByType(annotationClass);
//判断当前类获取到的注解数组是否为0
if (result.length == 0 &&
this instanceof Class &&
//判断定义注解上是否使用了@Inherited元注解
AnnotationType.getInstance(annotationClass).isInherited()) {
//从父类获取
Class<?> superClass = ((Class<?>) this).getSuperclass();
if (superClass != null) {
// Determine if the annotation is associated with the
// superclass
result = superClass.getAnnotationsByType(annotationClass);
}
}
return result;
}
注解中定义了名为value的元素,在使用该注解时,如果该元素是唯一需要赋值的元素,则无需使用key=value的语法,而只需在括号内给出value元素所需的值即可。元素名必须为value。