java注解本质是继承java.lang.annotation.annotation的特殊接口,作为元数据为代码打标签,不改变逻辑但通过编译器、反射或框架处理器实现配置、校验与增强,核心价值在于解耦业务与配置。

Java 注解是面试高频考点,核心不在死记硬背,而在理清“为什么存在”和“怎么被用起来”这两条主线。重点抓注解的定位(元数据)、生命周期控制、作用目标约束、以及与反射联动的实际路径。
注解的本质和存在意义
注解不是代码逻辑的一部分,而是一类编译期标记,本质是继承 java.lang.annotation.Annotation 的接口,由 JVM 动态生成代理对象。它的价值在于解耦——把配置信息从主业务中抽离出来,让框架(如 Spring)能统一扫描、识别并执行对应行为(比如 @Controller 注册 Bean、@Transactional 开启事务)。
- 它本身不运行,也不改变字节码指令
- 真正起作用的是配套的处理器:编译期靠 Annotation Processor,运行期靠反射 + 自定义逻辑
- 没有 @Retention(RetentionPolicy.RUNTIME),运行时就拿不到;没有 @Target,IDE 会报错或无法使用
四个元注解必须闭环理解
自定义注解时,@Retention、@Target、@Documented、@Inherited 这四个元注解要成对思考,不能孤立记忆:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- @Retention 决定“能活多久”:SOURCE(只在源码)、CLASS(进 class 文件但反射拿不到)、RUNTIME(反射可用,最常用)
-
@Target 规定“能贴在哪”:METHOD(方法)、TYPE(类/接口)、FIELD(字段)等,可组合使用,如
@Target({METHOD, TYPE}) - @Documented 是个“文档开关”:加了它,javadoc 会把该注解也生成进 API 文档
- @Inherited 控制“是否向下传递”:仅对类级别注解生效,子类自动继承父类的该注解(注意:方法、字段上的注解不继承)
运行时读取注解的关键路径
面试常问“怎么获取一个方法上的 @LogExecutionTime?”,答案不是调 API,而是讲清楚反射链路:
- 先拿到 Class 对象(比如
Class.forName("com.example.Service")) - 再获取 Method 对象(
clazz.getMethod("doWork")) - 调用
method.isAnnotationPresent(LogExecutionTime.class)判断是否存在 - 用
method.getAnnotation(LogExecutionTime.class)拿到注解实例(其实是 JDK 动态代理对象) - 最后调用注解方法,如
log.value()获取配置值,据此执行日志打印等逻辑
常见误区和实战提醒
很多候选人栽在细节上,这些点面试官特别爱追问:
- 注解元素只能是基本类型、String、Class、枚举、其他注解,或以上类型的数组;不能是任意对象或泛型
- 注解默认值用
default关键字,且必须是编译期常量(不能是 new Date() 或 methodCall()) - @Override 等内置注解是 SOURCE 级别,编译完就丢,所以运行时反射 getAnnotation 拿不到
- Spring 的 @Autowired 是 RUNTIME 级别,配合 BeanFactoryPostProcessor 或 InstantiationAwareBeanPostProcessor 在 IOC 容器启动时处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










