@Inherited是Java中唯一控制注解类继承性的元注解,仅对@Target(TYPE)且直接继承的类生效,不适用于接口实现、间接继承及方法/字段注解。

@Inherited 是 Java 中唯一一个用于控制注解是否可被子类继承的元注解,但它只对类级别(TYPE)的注解生效,且有重要限制:它仅作用于类的继承关系,不适用于方法或字段;并且只对直接继承有效,不支持接口实现或间接继承(如祖父类)。
@Inherited 的基本规则
当一个类被标注了带有 @Inherited 的注解时,它的直接子类(用 extends 声明)在调用 getAnnotation(Class) 时,能获取到该注解;但若父类是通过接口实现、或者注解在接口上,则不会被继承。
- 仅适用于
@Target(ElementType.TYPE)的注解(即只能标注在类、接口、枚举上) - 子类必须是父类的直接继承者(
class Sub extends Parent),不能是“继承链更远”的类 - 接口上的 @Inherited 注解不会被实现类继承(Java 规范明确不支持)
- 即使父类注解没加 @Inherited,子类也无法通过反射读取该注解——继承性由注解自身声明决定,不是由子类控制
正确使用示例
定义一个可继承的注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyMarker {
String value() default "";
}
父类使用它:
立即学习“Java免费学习笔记(深入)”;
@MyMarker("parent")
class Parent { }
子类继承后可读取:
class Child extends Parent { }
// 运行时可获取
MyMarker ann = Child.class.getAnnotation(MyMarker.class); // 返回非 null,值为 "parent"
常见误区与不可行情况
以下情形不会触发 @Inherited 的继承行为:
-
接口实现:
class Impl implements MyInterface→ 即使MyInterface有 @Inherited 注解,Impl拿不到 -
间接继承:
GrandChild extends Child extends Parent→GrandChild无法通过反射直接拿到Parent上的 @Inherited 注解(除非Child也显式标注) - 方法/字段注解:哪怕加了 @Inherited,对 METHOD 或 FIELD 标注的注解也完全无效
- 运行时未保留:如果注解的 @Retention 不是 RUNTIME,反射时根本不可见,@Inherited 失去意义
替代方案(当 @Inherited 不满足需求时)
若需支持接口、多层继承或方法级传播,需手动处理:
- 遍历继承链:
Class.getSuperclass()向上查找,直到 Object,逐个调用getAnnotation() - 检查接口:
Class.getInterfaces()获取直接实现的接口,再递归其父接口(注意接口无 @Inherited 语义,需自行约定) - 封装工具方法,例如:
AnnotationUtils.findAnnotation(clazz, MyMarker.class),内部统一处理继承逻辑


















