Java 注解(Annotation)是 Java 5 引入的一种元数据(metadata)机制,用于为代码提供附加信息,不直接影响代码逻辑,但可以通过编译器、工具或运行时环境解析并执行特定操作。


一、注解的基本概念

  1. 用途

    • 标记代码行为:如 @Override 标记方法重写。
    • 携带元数据:如 @Test 标记测试方法。
    • 替代配置文件:如 Spring 框架中的 @Component
    • 编译时检查:如 @FunctionalInterface 校验函数式接口。
    • 运行时处理:如通过反射读取注解并执行逻辑。
  2. 分类

    • 内置注解:Java 提供的常见注解(如 @Override@Deprecated)。
    • 元注解:用于定义其他注解的注解(如 @Target@Retention)。
    • 自定义注解:用户自定义的注解。

二、内置注解

1. @Override

  • 作用:标记方法为重写父类方法,编译器会校验是否符合重写规则。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Animal {
    void eat() {
    System.out.println("Animal is eating.");
    }
    }

    class Dog extends Animal {
    @Override
    void eat() {
    System.out.println("Dog is eating.");
    }
    }

2. @Deprecated

  • 作用:标记方法或类已过时,编译器会发出警告。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class DeprecatedDemo {
    @Deprecated
    public void oldMethod() {
    System.out.println("This method is deprecated.");
    }

    public static void main(String[] args) {
    DeprecatedDemo demo = new DeprecatedDemo();
    demo.oldMethod(); // 编译器会警告
    }
    }

3. @SuppressWarnings

  • 作用:抑制编译器警告。
  • 常用参数
    • deprecation:忽略过时方法警告。
    • unchecked:忽略未检查类型转换警告。
    • all:忽略所有警告。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import java.util.ArrayList;
    import java.util.List;

    public class SuppressWarningsDemo {
    @SuppressWarnings("unchecked")
    public void addToList(List list) {
    list.add("Item");
    }
    }

三、元注解

元注解是用于定义注解的注解,常见的元注解包括:

1. @Target

  • 作用:指定注解可以应用的程序元素类型。
  • 可选值
    • ElementType.TYPE:类、接口、枚举。
    • ElementType.METHOD:方法。
    • ElementType.FIELD:字段。
    • ElementType.PARAMETER:方法参数。
    • ElementType.CONSTRUCTOR:构造方法。
    • ElementType.ANNOTATION_TYPE:注解类型。
    • ElementType.LOCAL_VARIABLE:局部变量。
  • 示例
    1
    2
    3
    4
    @Target({ElementType.METHOD, ElementType.TYPE})
    public @interface MyAnnotation {
    String value() default "";
    }

2. @Retention

  • 作用:指定注解的保留策略(生命周期)。
  • 可选值
    • RetentionPolicy.SOURCE:仅保留在源代码中(编译时丢弃),如 @Override
    • RetentionPolicy.CLASS:保留在字节码中(运行时不可见,默认值)。
    • RetentionPolicy.RUNTIME:保留在运行时,可通过反射获取。
  • 示例
    1
    2
    3
    4
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    String value() default "";
    }

3. @Documented

  • 作用:指示注解应包含在 Javadoc 文档中。
  • 示例
    1
    2
    3
    4
    5
    @Documented
    @Target(ElementType.METHOD)
    public @interface MyAnnotation {
    String value() default "";
    }

4. @Inherited

  • 作用:指示注解可以被子类继承。
  • 示例
    1
    2
    3
    4
    5
    @Inherited
    @Target(ElementType.TYPE)
    public @interface MyAnnotation {
    String value() default "";
    }

5. @Repeatable(Java 8+)

  • 作用:允许同一个注解在同一个程序元素上重复使用。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Repeatable(Authorities.class)
    public @interface Authority {
    String role();
    }

    public @interface Authorities {
    Authority[] value();
    }

    @Authority(role = "Admin")
    @Authority(role = "Editor")
    public class MyClass {
    // ...
    }

四、自定义注解

1. 定义自定义注解

  • 语法:使用 @interface 定义注解。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import java.lang.annotation.*;

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    String value() default "default";
    int priority() default 1;
    boolean enabled() default true;
    }

2. 使用自定义注解

  • 示例
    1
    2
    3
    4
    5
    6
    public class AnnotationDemo {
    @MyAnnotation(value = "important", priority = 2, enabled = true)
    public void doSomething() {
    System.out.println("Executing method...");
    }
    }

3. 通过反射读取注解

  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import java.lang.annotation.Annotation;

    public class AnnotationReader {
    public static void main(String[] args) throws Exception {
    Class<AnnotationDemo> clazz = AnnotationDemo.class;
    for (Method method : clazz.getDeclaredMethods()) {
    if (method.isAnnotationPresent(MyAnnotation.class)) {
    MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
    System.out.println("Method: " + method.getName());
    System.out.println("Value: " + annotation.value());
    System.out.println("Priority: " + annotation.priority());
    System.out.println("Enabled: " + annotation.enabled());
    }
    }
    }
    }

五、注解的高级应用

1. 枚举类型与默认值

  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public @interface Greeting {
    enum FontColor { BLUE, RED, GREEN }
    String name();
    FontColor fontColor() default FontColor.RED;
    }

    public class AnnotationTest {
    @Greeting(name = "default", fontColor = Greeting.FontColor.BLUE)
    public void sayHello() {
    System.out.println("Hello!");
    }
    }

2. 注解与框架结合

  • Spring 框架示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Service
    public class UserService {
    @Autowired
    private UserRepository userRepository;
    }

    @RestController
    @RequestMapping("/users")
    public class UserController {
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
    return userRepository.findById(id);
    }
    }

3. 注解处理器(APT)

  • 作用:在编译期生成代码(如 Lombok 的 @Data)。
  • 示例
    1
    2
    3
    4
    5
    @Data
    public class User {
    private String name;
    private int age;
    }

六、注解的优势与应用场景

  1. 优势

    • 提高代码可读性:通过注解明确代码意图。
    • 减少冗余配置:替代 XML 配置文件。
    • 灵活扩展性:通过注解和反射实现动态功能。
  2. 应用场景

    • 框架开发:Spring、Hibernate 等框架大量使用注解。
    • 代码生成:Lombok 通过注解简化代码。
    • 编译检查:自定义注解校验代码规范。
    • 运行时处理:通过反射读取注解并执行逻辑。

七、总结

Java 注解是现代 Java 开发中不可或缺的工具,它通过元数据的形式为代码提供附加信息,结合反射和注解处理器,可以实现强大的功能。掌握注解的定义、使用和元注解的应用,能够显著提升代码的灵活性和可维护性。