跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何在 Java 中通过 Inherited 注解让父类上的标注信息能够自动被子类继承

@Inherited仅使被其标记的类级注解可被子类继承,不适用于方法、字段或接口,且要求父类直接标注该注解;若未生效,需手动遍历继承链查找。 Java 里没有
@Inherited
注解的“自动继承”这回事——它只对类上直接标注的注解生效,且仅限于被
@Inherited
元注解标记过的注解,还不能穿透到方法、字段或接口实现上。 为什么 @Inherited 看起来“不工作” 这是最常踩的坑:
@Inherited
不是让子类“继承父类所有注解”,而是个非常窄的机制:当一个类 A 被某个带
@Inherited
的注解(比如自定义的
@MyAnnotation
)标注时,它的子类 B 在调用
B.class.getAnnotation(MyAnnotation.class)
才可能拿到该注解——前提是
@MyAnnotation
自身声明了
@Inherited
,且 A 是直接标注者。 父类方法上的注解,无论是否加
@Inherited
,子类重写后都拿不到(
getDeclaredMethod(...).getAnnotation(...)
查的是当前声明处) 接口上的注解永远不会被实现类继承(
@Inherited
对
@interface
声明无效) 如果父类没直接标注,而是通过其他注解(如 Spring 的
@Service
)间接获得,那更不会传递 如何真正让子类“看到”父类的注解 得自己写逻辑扫描继承链。核心是遍历
Class.getSuperclass()
和
Class.getInterfaces()
,逐层调用
getAnnotation()
。 只查类层级(不递归查接口),用
Class> clazz = targetClass; while (clazz != null) { ... clazz = clazz.getSuperclass(); }
要支持接口,需额外处理
clazz.getInterfaces()
并递归其父接口(注意避免循环,比如
Iterable
和
Collection
的关系) Spring 的
AnnotationUtils.findAnnotation()
就是这么干的,它比原生
getAnnotation()
多走了一层继承查找 示例片段:
public static T findAnnotation(Class clazz, Class annotationType) { T ann = clazz.getAnnotation(annotationType); if (ann != null) return ann; Class sup = clazz.getSuperclass(); if (sup != null) { ann = findAnnotation(sup, annotationType); if (ann != null) return ann; } return null; }
@Inherited 的唯一有效使用场景 只有当你在定义自己的注解,并希望它能被子类“类级别继承”时,才需要加上
@Inherited
。否则,即使写了也毫无作用。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 立即学习 “ Java免费学习笔记(深入) ”; 必须写在自定义注解定义上:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface MyConfig { String value() default ""; }
父类标注后,子类才能通过
SubClass.class.getAnnotation(MyConfig.class)
拿到(前提是没被子类同名注解覆盖) 如果去掉
@Inherited
,哪怕父子类结构完全一样,子类也查不到 Spring Boot 的
@Configuration
、JUnit5 的
@TestInstance
都用了这个机制,但它们内部还做了更多兼容处理 真正麻烦的从来不是加不加
@Inherited
,而是你得想清楚:到底要继承哪一层的注解?类?方法?参数?有没有元注解嵌套?要不要考虑桥接方法?这些都得手动处理,JVM 不会替你猜。

相关文章