@inherited仅使被其修饰且@retention(runtime)、@target(type)的类级注解在子类反射中可查,通过getannotations()等方法沿extends链向上查找,但不适用于接口实现、方法字段注解或非运行时注解。

要理解 @Inherited 在子类中如何体现注解继承性,关键不是“加了就能用”,而是看清它生效的边界条件和实际表现形式。它不改变字节码,只影响反射行为。
注解必须是类级别且运行时可见
@Inherited 只对作用在类上的注解起作用,且该注解自身必须同时满足:
- @Target(ElementType.TYPE):只能标注在类、接口、枚举等类型上,不能标在方法或字段上
- @Retention(RetentionPolicy.RUNTIME):必须保留到运行期,否则 Class.getAnnotation() 根本查不到
子类“继承”只是反射查找路径的延伸
子类 class 文件里并不会多出任何注解信息。所谓“继承”,是指调用以下方法时 JVM 自动向上遍历父类:
- getAnnotations():返回当前类 + 父类中所有被 @Inherited 修饰的运行时注解
- isAnnotationPresent(YourAnno.class):返回 true,哪怕子类没显式声明
- getAnnotation(YourAnno.class):能拿到父类上定义的注解实例
但 getDeclaredAnnotations() 始终只返回子类自己声明的注解,完全不查父类。
哪些情况完全不生效
@Inherited 的限制非常明确,以下场景一律无效:
- 注解标在方法、字段、参数或局部变量上——哪怕加了 @Inherited,子类重写方法也拿不到父方法的注解
- 类实现接口:接口上的 @Inherited 注解,实现类无法通过反射获取
- 接口之间extends:子接口不会继承父接口的任何注解
- 注解的 @Retention 是 SOURCE 或 CLASS:运行时反射不可见,继承性无从谈起
多层继承也支持,但仅限直接 extends 链
只要继承链是单根的(A → B → C),C 类调用 getAnnotation() 仍能拿到 A 类上被 @Inherited 修饰的注解。这说明 JVM 查找时会一直向上直到 Object,而不是只看直接父类。但要注意,这种查找只走 extends 路径,不走 implements 或组合关系。










