@Inherited仅对类级别注解生效,要求被修饰注解同时满足@Target(ElementType.TYPE)和@Retention(RetentionPolicy.RUNTIME),子类才能通过Class.getAnnotation()获取父类注解;对方法、字段等无效。

@Inherited 只对类级别注解生效
默认情况下,子类不会自动获得父类上声明的注解——哪怕子类继承了父类。只有显式加上 @Inherited 元注解,并且该注解作用在类(ElementType.TYPE)上,子类才能通过 Class.getAnnotation() 拿到父类的注解实例。
常见错误现象:给方法加了 @Inherited 注解,结果子类重写该方法后调用 getMethod().getAnnotation() 仍返回 null。这是因为 @Inherited 对方法、字段、参数等位置完全无效。
-
@Inherited是 Java 内置元注解,只能修饰其他注解,不能直接加在类或方法上 - 被修饰的注解必须同时满足:
@Target(ElementType.TYPE)+@Retention(RetentionPolicy.RUNTIME) - 接口上的
@Inherited注解不会被实现类继承(即使类实现了该接口)
如何正确声明一个可被继承的注解
关键不是“怎么用 @Inherited”,而是“怎么定义一个能被子类继承的注解”。下面是最小可用示例:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyConfig {
String value() default "";
}
然后这样使用:
@MyConfig("parent")
class Parent {}
class Child extends Parent {} // Child.class.getAnnotation(MyConfig.class) != null
- 如果把
@Target改成ElementType.METHOD,哪怕加了@Inherited,子类方法也拿不到 - 如果
@Retention是CLASS或SOURCE,运行时反射根本看不到该注解 - 子类必须是直接继承(单层),多层继承也生效;但间接继承(如 A → B → C)中 C 也能拿到 A 的
@MyConfig
方法注解无法靠 @Inherited 继承,得手动向上查找
子类重写父类方法时,父类方法上的注解不会自动出现在子类方法对象上。这是 JVM 规范限制,@Inherited 不起作用。
实际开发中,若需获取“继承链上最近的方法注解”,必须自己遍历:
public static <A extends Annotation> A findMethodAnnotation(
Class<?> clazz, String methodName, Class<A> annoType) throws NoSuchMethodException {
while (clazz != null && clazz != Object.class) {
try {
Method m = clazz.getDeclaredMethod(methodName);
A anno = m.getAnnotation(annoType);
if (anno != null) return anno;
} catch (NoSuchMethodException ignored) {}
clazz = clazz.getSuperclass();
}
return null;
}
- 注意要用
getDeclaredMethod(),不是getMethod()(后者不返回 private 方法) - 只查当前类及其父类,不查接口(接口方法默认是 public,但注解在接口方法上同样不会被实现类继承)
- Spring 的
AnnotationUtils.findAnnotation()就是这个逻辑的封装版
容易忽略的兼容性细节
看似简单,但几个边界情况常导致线上 bug:
- 子类加了同名注解(如父类有
@MyConfig("a"),子类也加了@MyConfig("b")),子类会覆盖父类注解,@Inherited不触发“合并”行为 - 泛型类继承(如
class Child extends Parent<String>)不影响@Inherited生效 - 使用 Lombok 的
@EqualsAndHashCode或@Data时,生成的getClass().getAnnotation()调用可能因字节码增强而异常,建议在构造完对象后再查注解
真正需要跨层级复用注解语义时,别依赖 @Inherited 的自动传播,优先考虑统一提取配置、或用工具类做显式查找——它更可控,也更容易单元测试。

















