@inherited仅在getannotations()中沿extends链向上查找类注解,需同时满足:注解自身被@inherited修饰、标注于类上、保留策略为runtime、子类显式继承父类。

@Inherited 不是让子类“自动拥有”父类注解,而是改变反射查询行为——它只在调用 getAnnotations() 时沿 extends 链向上查找,且仅对类生效。
哪些场景下 @Inherited 才真正起作用
必须同时满足以下四个条件:
- 自定义注解本身被
@Inherited修饰 - 该注解标注在 类(
ElementType.TYPE) 上,不能标在方法、字段、参数或接口上 - 注解的保留策略为
@Retention(RetentionPolicy.RUNTIME) - 子类通过
extends显式继承父类(单继承链),不涉及implements或组合
为什么子类 getDeclaredAnnotations() 看不到父类注解
getDeclaredAnnotations() 的设计原则是“只看本类显式声明”,完全不走继承链。哪怕父类有 @Inherited 注解,子类字节码里也不会多出任何注解信息。这是 JVM 反射机制的底层约定,不是 bug,而是明确的行为边界。
若需判断是否“逻辑上继承了”某个注解,应统一使用 isAnnotationPresent(YourAnno.class) 或 getAnnotation(YourAnno.class) ——它们内部已集成向上查找逻辑。
常见失效情况一目了然
以下情形中,@Inherited 完全无效:
- 注解加在接口上,实现类无法继承(Java 多实现路径无法确定优先级)
- 注解加在父类的方法上,子类重写后调用
method.getAnnotations()拿不到父方法的注解 - 注解的
@Retention是SOURCE或CLASS,运行时反射根本不可见 - 子类自己也声明了同类型的注解,会覆盖继承来的值(
getAnnotations()返回的是子类声明 + 继承来的组合,但同类型只取子类的)
多层继承与抽象类的支持性
只要继承链是干净的 A extends B extends C,C 类调用 getAnnotation(X.class) 就能一路查到 A 类上的 @X(前提是 X 带 @Inherited 且 RUNTIME)。抽象父类同样适用——它和普通父类在继承机制中无差别。关键不在“是否具体”,而在“是否在 extends 路径上”。
注意:即使子类同时 extends Parent 又 implements Interface,JVM 也只追溯 Parent → Object 这一条线,接口路径被完全忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











