1. 概述

本文将深入探讨 Java 语言的核心特性之一——JDK 中提供的内置注解。这些注解是 Java 开发中不可或缺的工具,掌握它们能显著提升代码质量和开发效率。

2. 什么是注解

简单来说,注解就是以 "@" 符号开头的 Java 类型

自 Java 1.5 版本引入注解后,它彻底改变了我们设计应用程序的方式。Spring 和 Hibernate 等框架就是重度依赖注解的典型例子。

本质上,注解为绑定的源代码附加额外元数据。通过在方法、接口、类或字段上添加注解,我们可以:

  1. ✅ 向编译器提供警告和错误信息
  2. ✅ 在编译时操作源代码
  3. ✅ 在运行时修改或检查行为

3. Java 内置注解

现在让我们看看 JDK 自带的核心注解。首先是编译相关注解:

  1. @Override
  2. @SuppressWarnings
  3. @Deprecated
  4. @SafeVarargs
  5. @FunctionalInterface
  6. @Native

这些注解用于生成或抑制编译器警告和错误。建议规范使用它们,能有效避免未来潜在的错误。

3.1. @Override

@Override 注解用于明确标记方法覆盖父类行为。虽然不强制使用,但加上它能:

  • ✅ 防止拼写错误导致的意外重载
  • ✅ 提高代码可读性

3.2. @SuppressWarnings

@SuppressWarnings 用于忽略特定代码段的编译警告。常见场景包括:

  • 使用泛型时的未检查类型警告
  • 已弃用 API 的警告

⚠️ 建议谨慎使用,仅当确认警告无害时才抑制。

3.3. @Deprecated

@Deprecated 用于标记不再建议使用的 API。Java 9 后还增强了该注解:

@Deprecated(since = "1.2", forRemoval = true)
public void oldMethod() {}

3.4. @FunctionalInterface

Java 8 引入函数式编程后,单抽象方法接口(SAM) 变得重要。使用 @FunctionalInterface 可明确意图:

@FunctionalInterface
public interface Adder {
    int add(int a, int b);
}

即使不加注解,Adder 仍可作为 lambda 使用:

Adder adder = (a,b) -> a + b;
int result = adder.add(4,5);

但若误添加第二个方法:

@FunctionalInterface
public interface Adder { 
    // 编译器会报错:不是 SAM 接口
    int add(int a, int b);
    int div(int a, int b);
}

核心价值:像 @Override 一样,将错误局限在接口定义处,避免扩散到所有使用点。

3.5. @Native

Java 8 新增的 @Native 仅适用于字段,表示该常量可能被本地代码引用。典型用法:

public final class Integer {
    @Native public static final int MIN_VALUE = 0x80000000;
    // 省略其他代码
}

该注解还能辅助工具生成头文件。

4. 元注解

元注解是用于注解其他注解的注解。Java 提供了五个元注解:

  1. @Target
  2. @Retention
  3. @Inherited
  4. @Documented
  5. @Repeatable

4.1. @Target

定义注解的适用范围,支持 12 种元素类型。查看 @SafeVarargs 源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface SafeVarargs {}

❌ 错误示例:若注解未限定 @Target,可能导致误用。

4.2. @Retention

控制注解的生命周期,三种策略:

  1. RetentionPolicy.SOURCE – 仅源码可见
  2. RetentionPolicy.CLASS – 编译时可见(默认)
  3. RetentionPolicy.RUNTIME – 运行时可见

示例:

@Retention(RetentionPolicy.RUNTIME)
@Target(TYPE)
public @interface RuntimeAnnotation {}

测试验证:

@Test
public void testRuntimeRetention() {
    Annotation[] annotations = new AnnotatedClass().getClass().getAnnotations();
    assertThat(annotations.length, is(1)); // 仅 RUNTIME 注解被保留
}

4.3. @Inherited

使注解自动被子类继承。示例:

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedAnnotation {}

@InheritedAnnotation
public class BaseClass {}

public class DerivedClass extends BaseClass {}

验证:

@Test
public void testInheritance() {
    InheritedAnnotation annotation = new DerivedClass()
        .getClass()
        .getAnnotation(InheritedAnnotation.class);
    assertThat(annotation, notNullValue());
}

⚠️ 注意:仅对类注解有效,接口/方法注解不继承。

4.4. @Documented

将注解纳入 Javadoc。示例:

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelCell {
    int value();
}

public class Employee {
    @ExcelCell(0)
    public String name;
}

生成的 Javadoc 会显示字段注解: Javadoc 示例

4.5. @Repeatable

允许在同一元素重复使用注解。Java 7 前需要容器注解:

@Schedules({
    @Schedule(time = "15:05"),
    @Schedule(time = "23:00")
})
void scheduledAlarm() {}

Java 8 引入 @Repeatable 后简化为:

@Repeatable(Schedules.class)
public @interface Schedule {
    String time() default "09:00";
}

public @interface Schedules {
    Schedule[] value();
}

// 使用时无需显式容器
@Schedule
@Schedule(time = "15:05")
@Schedule(time = "23:00")
void scheduledAlarm() {}

✅ 迁移友好:旧代码可直接升级为新用法。

5. 总结

本文系统梳理了 Java 内置注解体系,包括:

  • 编译相关注解(@Override@Deprecated 等)
  • 元注解(@Target@Retention 等)
  • Java 8+ 新增特性(@FunctionalInterface@Repeatable

掌握这些注解能帮助开发者:

  1. ✅ 编写更健壮的代码
  2. ✅ 避免"踩坑"
  3. ✅ 提升框架开发能力

本文所有示例代码可在 GitHub 获取。


原始标题:Overview of Java Built-in Annotations | Baeldung

« 上一篇: Java二叉树的实现
» 下一篇: Hibernate 拦截器详解