@Inherited仅对类层级注解生效,需同时满足@Inherited、@Target(TYPE)、@Retention(RUNTIME)三条件;方法、字段、接口及参数注解均不继承,子类重写后须手动遍历继承链查找。
Java 中的注解默认不继承,@Inherited 是唯一能影响继承行为的元注解,但它只对类级别(TYPE)注解生效,且有明确限制——不能用于接口、方法或参数,也不能跨重写传播。
只有同时满足以下条件,子类才能通过 getAnnotation() 直接获取父类的注解:
@Inherited
@Target(ElementType.TYPE))例如:
@Inherited@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface MyService { String value() default "";}@MyService("UserService")public class UserServiceImpl {}public class AdminServiceImpl extends UserServiceImpl {} // ✅ 继承成功
调用 AdminServiceImpl.class.getAnnotation(MyService.class) 将返回非 null 注解实例。
立即学习“Java免费学习笔记(深入)”;
即使方法上的注解也标注了 @Inherited,只要子类重写了该方法,就无法通过反射在子类方法对象上直接获取该注解:
@MyLog 注解 → 子类未重写时,getMethod(...).getAnnotation(MyLog.class) 可取到@Override 了该方法 → 即使方法体为空,注解也不会出现在子类方法对象上Parameter.isAnnotationPresent(...) 返回 false这是 JVM 规范行为,@Inherited 对 METHOD/PARAMETER 无效。
无论接口或其实现类是否使用 @Inherited,都不会触发继承:
IUser 标注 @MyApi(带 @Inherited)UserImpl implements IUser → UserImpl.class.getAnnotation(MyApi.class) 一定为 nullIAdmin extends IUser → 同样无法继承 @MyApi
接口不是继承关系(is-a),而是契约关系(implements),JVM 不为此提供注解传递机制。
当需要“逻辑继承”方法注解时,需手动沿继承链查找:
Class.getSuperclass() 逐级向上获取父类getMethod(name, paramTypes) 并检查注解NoSuchMethodException 或到达 Object.class 停止Spring 的 AnnotationUtils.findAnnotation() 就是这种策略的封装,支持跨层级查找方法和参数注解。