Java 注解(Annotation)自 Java 5 引入以来,已成为现代 Java 开发中不可或缺的一部分。它们如同代码中的“标签”或“元数据”,为类、方法、字段等程序元素附加额外信息,从而被编译器、开发工具或运行时框架识别和处理。
从 @Override 到 Spring 的 @Autowired,注解极大地提升了代码的可读性、可维护性和开发效率。本文将带你系统掌握 Java 注解的核心概念、自定义方法、处理机制与典型应用场景。
Java 注解以 @注解名 的形式出现在代码中,附着于类、接口、方法、字段、参数等元素之上,用于描述这些元素的额外信息。
@Override
public String toString() {
return "User{}";
}这里的 @Override 并不是注释,而是一个编译器指令:它告诉编译器“这个方法是重写父类方法的”,如果父类没有该方法,编译将报错。
💡 注解本身不改变程序逻辑,但它可以影响程序的行为——通过编译器、工具或框架对它的“解读”。
用途 | 说明 | 示例 |
|---|---|---|
编译器指令 | 指导编译器进行检查或警告 | @Override, @SuppressWarnings |
代码分析 | 工具通过注解生成文档、检查规范 | @Documented, SonarQube 分析 |
运行时处理 | 框架在运行时读取注解并执行逻辑 | Spring 的 @Autowired, JPA 的 @Entity |
Java 提供了多个常用内置注解,帮助开发者编写更安全、清晰的代码:
注解 | 作用 |
|---|---|
@Override | 确保方法正确重写父类方法,防止拼写错误 |
@Deprecated | 标记已过时的方法或类,建议不再使用 |
@SuppressWarnings | 抑制编译器警告(如未使用变量、泛型不安全等) |
@FunctionalInterface | 确保接口是函数式接口(仅含一个抽象方法) |
@Deprecated(since = "1.8", forRemoval = true)
public void oldMethod() {
// 已废弃方法
}
@SuppressWarnings("unchecked")
public List<String> badCast() {
return (List<String>) new ArrayList(); // 忽略类型转换警告
}✅ 使用
@Deprecated时建议添加since和forRemoval属性,提高可维护性。
Java 允许我们定义自己的注解,为项目添加语义化标签。
使用 @interface 关键字定义注解:
public @interface MyAnnotation {
String author() default "Anonymous";
int version() default 1;
String[] tags() default {};
}author, version, tags 是注解的成员(元素)default 默认值@MyAnnotation(
author = "Zhang San",
version = 2,
tags = {"security", "core"}
)
public class UserService {
// ...
}元注解(Meta-Annotation)是“注解的注解”,用于定义注解的行为和作用范围。
@Retention:注解的生命周期值 | 说明 |
|---|---|
RetentionPolicy.SOURCE | 仅保留在源码中,编译后丢弃(如 @Override) |
RetentionPolicy.CLASS | 保留在 .class 文件中,但运行时不可见 |
RetentionPolicy.RUNTIME | 保留在 .class 中,并可在运行时通过反射获取 |
✅ 框架常用
RUNTIME,如 Spring、JPA。
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation { ... }@Target:注解的适用位置值 | 说明 |
|---|---|
ElementType.TYPE | 类、接口、枚举 |
ElementType.METHOD | 方法 |
ElementType.FIELD | 字段 |
ElementType.PARAMETER | 参数 |
ElementType.CONSTRUCTOR | 构造器 |
ElementType.LOCAL_VARIABLE | 局部变量 |
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime { }元注解 | 作用 |
|---|---|
@Documented | 注解将包含在 Javadoc 文档中 |
@Inherited | 子类可继承父类的注解 |
@Repeatable | 允许在同一位置重复使用该注解 |
💡
@Repeatable示例: java深色版本@Repeatable(Schedules.class) public @interface Schedule { String time(); } @Schedule(time = "morning") @Schedule(time = "evening") public void dailyTask() { ... }
注解本身只是“静态标签”,要发挥其作用,必须通过注解处理器来解析和执行逻辑。
这是最常见的方式,适用于 Spring、MyBatis 等框架。
// 读取类上的注解
MyAnnotation classAnn = UserService.class.getAnnotation(MyAnnotation.class);
System.out.println("作者:" + classAnn.author());
System.out.println("版本:" + classAnn.version());
// 读取方法上的注解
Method method = UserService.class.getMethod("createUser");
if (method.isAnnotationPresent(LogExecutionTime.class)) {
System.out.println("该方法需要记录执行时间");
}✅ 前提:注解必须使用
@Retention(RUNTIME)。
APT 是在编译阶段处理注解的机制,常用于生成代码。
例如:Lombok 使用 APT 在编译时自动生成 getter、setter、toString 等方法。
javax.annotation.processing.Processor 接口process() 方法,扫描并处理目标注解Filer 生成新的 Java 文件META-INF/services/javax.annotation.processing.Processor 注册处理器🔍 APT 常用于 ORM 框架、Builder 模式代码生成等场景。
我们来实现一个 @LogExecutionTime 注解,自动记录方法执行耗时。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogExecutionTime {
}public class BusinessService {
@LogExecutionTime
public void processData() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("业务数据处理完成");
}
}public class LogProxy implements InvocationHandler {
private final Object target;
public LogProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 检查是否有 @LogExecutionTime 注解
if (method.isAnnotationPresent(LogExecutionTime.class)) {
long start = System.currentTimeMillis();
System.out.println("⏰ 开始执行: " + method.getName());
Object result = method.invoke(target, args);
long end = System.currentTimeMillis();
System.out.println("✅ 执行结束: " + method.getName() + ", 耗时: " + (end - start) + "ms");
return result;
}
// 无注解,直接调用
return method.invoke(target, args);
}
}BusinessService service = new BusinessService();
BusinessService proxy = (BusinessService) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new LogProxy(service)
);
proxy.processData();⏰ 开始执行: processData
业务数据处理完成
✅ 执行结束: processData, 耗时: 204ms✅ 成功实现“无侵入式”性能监控!
框架/工具 | 注解示例 | 功能 |
|---|---|---|
Spring | @Component, @Autowired, @RestController | 依赖注入、AOP、Web 映射 |
JPA/Hibernate | @Entity, @Table, @Column | 对象关系映射(ORM) |
JUnit/TestNG | @Test, @Before, @After | 标记测试方法 |
Lombok | @Getter, @Setter, @Data | 自动生成样板代码 |
Swagger | @ApiOperation, @ApiModel | 生成 API 文档 |
Validation | @NotNull, @Size | 参数校验 |
@Cacheable、@Transactional。@Retention:运行时注解慎用,避免性能开销。@Documented 提升 API 可维护性。Java 注解是一种强大的元数据机制,它让代码具备了“自我描述”的能力。通过注解,我们可以实现:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。