如何获取类上的所有父注解?以Test类获取SuperAnnotation为例
这个问题很典型——Java默认不会自动帮你获取注解上的元注解(也就是你说的“父注解”),因为注解之间的继承逻辑和类继承不一样:哪怕你给SubAnnotation加了@SuperAnnotation,直接调用Test.class.getAnnotations()也只会拿到SubAnnotation本身。不过我们可以手动遍历注解的元注解来解决这个问题,下面给你具体的实现方案:
基础解决方案:直接获取元注解
首先要明确:每个注解本身也是一个Class对象,所以可以通过annotation.annotationType()拿到注解的类型,再调用getAnnotations()获取它上面的所有元注解。修改你的测试代码如下:
import java.lang.annotation.Annotation; @SubAnnotation public class Test { public static void main(String args[]) { // 第一步:获取Test类上的所有直接注解 Annotation[] classAnnotations = Test.class.getAnnotations(); for (Annotation classAnnot : classAnnotations) { System.out.println("类上的直接注解:" + classAnnot); // 第二步:获取当前注解的元注解(即你要的SuperAnnotation) Annotation[] metaAnnotations = classAnnot.annotationType().getAnnotations(); for (Annotation metaAnnot : metaAnnotations) { System.out.println("注解的元注解:" + metaAnnot); } } } } // 定义SuperAnnotation @Retention(RetentionPolicy.RUNTIME) public @interface SuperAnnotation { } // 定义SubAnnotation,标记了SuperAnnotation @Retention(RetentionPolicy.RUNTIME) @SuperAnnotation public @interface SubAnnotation { }
运行这段代码后,你会看到输出:
类上的直接注解:@SubAnnotation() 注解的元注解:@SuperAnnotation() 注解的元注解:@java.lang.annotation.Retention(value=RUNTIME)
这里除了SuperAnnotation,还会输出@Retention,因为它也是SubAnnotation的元注解。如果只想拿到自定义的元注解,可以加个判断过滤掉JDK自带的注解。
进阶方案:递归获取所有层级的元注解
如果你的注解体系更复杂(比如SuperAnnotation上面还有一层元注解),可以写一个递归方法来遍历所有层级的注解,避免遗漏:
import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; @SubAnnotation public class Test { public static void main(String args[]) { List<Annotation> allAnnotations = new ArrayList<>(); // 先收集类上的直接注解 Annotation[] classAnnotations = Test.class.getAnnotations(); for (Annotation annot : classAnnotations) { collectAllAnnotations(annot, allAnnotations); } // 输出所有收集到的注解 System.out.println("所有层级的注解:"); for (Annotation annot : allAnnotations) { System.out.println(annot); } } // 递归收集所有注解及元注解 private static void collectAllAnnotations(Annotation annotation, List<Annotation> result) { if (annotation == null || result.contains(annotation)) { return; // 避免循环引用,直接返回 } result.add(annotation); // 获取当前注解的所有元注解,继续递归 Annotation[] metaAnnotations = annotation.annotationType().getAnnotations(); for (Annotation metaAnnot : metaAnnotations) { collectAllAnnotations(metaAnnot, result); } } } // 定义SuperAnnotation,假设它还有自己的元注解 @Retention(RetentionPolicy.RUNTIME) @AnotherMetaAnnotation public @interface SuperAnnotation { } @Retention(RetentionPolicy.RUNTIME) public @interface AnotherMetaAnnotation { } @Retention(RetentionPolicy.RUNTIME) @SuperAnnotation public @interface SubAnnotation { }
这个工具方法会把SubAnnotation、SuperAnnotation、AnotherMetaAnnotation以及它们的@Retention注解都收集起来,非常适合复杂的注解场景。
注意事项:@Inherited的局限性
这里要提醒你:Java的@Inherited注解只作用于类之间的继承——比如如果Test类继承了一个带有注解的父类,子类会继承父类的注解,但它不会让注解继承自己的元注解,所以不要指望用@Inherited来解决这个问题,必须手动遍历元注解。
内容的提问来源于stack exchange,提问作者Domi.Zhang

