@inherited仅在反射查询类注解时启用向上查找机制,不复制、覆盖或合并注解;生效需同时满足三条件:注解声明@inherited、@target含elementtype.type、@retention为runtime;对方法、字段、接口等无效,本质是查找链而非真正继承。

Java 中的 @Inherited 并不解决“继承冲突”,它本身也不是为协调多个注解来源而设计的机制——它只是一种**反射查询时向上查找类注解的简化开关**。所谓“冲突”,往往源于开发者误以为它能自动复制、覆盖或合并注解,而实际它既不复制、也不覆盖、更不合并,只是让 getAnnotation() 在找不到本类注解时,多走一步去父类查一次。
只对类生效,且必须满足三个硬性条件
想让子类通过反射拿到父类的注解,缺一不可:
- 自定义注解本身要声明
@Inherited - 该注解的
@Target必须包含ElementType.TYPE(即只能标在类、接口、枚举等类型上) - 该注解的
@Retention必须是RetentionPolicy.RUNTIME(运行时保留,反射才能读到)
方法、字段、接口实现全都不买账
哪怕你在方法上加了带 @Inherited 的注解,子类重写后调用 getMethod().getAnnotation() 仍返回 null;接口上标注了同样注解,实现类也完全不会继承;字段、参数、构造器上的注解,@Inherited 对它们毫无影响。这不是 bug,是 JVM 规范明确限定的行为。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
不是“继承”,而是“查找链”
@Inherited 不会让子类字节码里真的多出一个注解声明。它只是让 Class.getAnnotation(Class) 方法在子类没声明该注解时,自动沿着 getSuperclass() 向上找,直到 Object 或找到为止。所以:
- 多层继承(A → B → C)没问题,C 能拿到 A 的注解,靠的是反射逐级查找,不是
@Inherited做了“广播” - 如果中间某一级(比如 B)自己也加了同名注解,但该注解类型没声明
@Inherited,那 C 就无法从 B 继承——B 的注解成了“断点”,查找链在此中断
真正需要跨层级获取时,得自己动手
框架如 Spring 的 AnnotationUtils.findAnnotation() 就是典型做法:手动遍历继承链和接口链。你要支持方法注解继承,就得循环调用 getDeclaredMethod() + getSuperclass();要兼容接口,还得递归展开 getInterfaces() 及其父接口(注意避免重复和循环)。别指望 @Inherited 替你完成这些。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










