Java注解(Annotations)的定义和使用详解

 更新时间:2025年03月11日 09:08:10   作者:冰糖心书房  
Java注解(Annotations)是Java5引入的一种元数据(Metadata),它提供了一种在源代码中嵌入补充信息的方式,这些信息可以被编译器、JVM或其他工具在编译时、运行时进行处理,注解本身不会直接影响程序的执行,但可以用来指导编译器、JVM或其他工具的行为,从而实现各种功能

Java 注解(Annotations)是 Java 5 引入的一种元数据(Metadata),它提供了一种在源代码中嵌入补充信息的方式,这些信息可以被编译器、JVM 或其他工具在编译时、运行时进行处理。

注解本身不会直接影响程序的执行,但可以用来指导编译器、JVM 或其他工具的行为,从而实现各种功能。

一、 注解的定义 (Annotation Definition)

什么是元数据 (Metadata)?

  • 元数据是描述数据的数据。 在 Java 中,元数据是指描述程序代码的数据,例如类、方法、字段等的属性信息。
  • 注解就是一种元数据,它可以用来描述类、方法、字段、参数、局部变量等程序元素。

注解的语法

@Retention(RetentionPolicy.RUNTIME) // 元注解,指定注解的保留策略
@Target({ElementType.METHOD, ElementType.TYPE}) // 元注解,指定注解可以应用的程序元素类型
public @interface MyAnnotation { // 定义一个注解

    // 注解成员 (Annotation Members)
    String name() default "Default Name"; // 默认值
    int value(); // 必须赋值

    Class<?> type() default void.class; //类型
}
  • @interface 关键字: 用于定义一个注解。
  • 注解名 (Annotation Name): 遵循 PascalCase 命名规范(每个单词首字母大写),例如 Override, Deprecated, WebServlet
  • 注解成员 (Annotation Members):
    • 类似于接口中的方法声明,但没有方法体。
    • 可以有默认值 (使用 default 关键字指定)。
    • 如果没有默认值,则在使用注解时必须显式赋值。
    • 成员的类型可以是原始类型、StringClass、枚举类型、注解类型或这些类型的数组。
    • 注解成员实际上类似于接口中的方法,这意味着它们可以有访问修饰符,但通常省略 (默认是 public)。
    • 注解成员后面要跟一对小括号,即使没有参数。

二、元注解 (Meta-Annotations)

元注解是用于修饰注解的注解,用于指定注解的特性。

1.@Retention

作用: 指定注解的保留策略 (Retention Policy),即注解在哪个阶段可用。

RetentionPolicy 枚举:

  • RetentionPolicy.SOURCE: 注解仅保留在源代码中,在编译时被丢弃。 例如,@Override 注解。
  • RetentionPolicy.CLASS: 注解保留在 class 文件中,但在运行时会被 JVM 丢弃。
  • RetentionPolicy.RUNTIME: 注解保留在 class 文件中,并且在运行时可以通过反射 API 获取。 这是最常用的保留策略,可以实现各种动态功能。

示例:

@Retention(RetentionPolicy.RUNTIME) // 指定注解在运行时可用
public @interface MyAnnotation {
    // ...
}

2.@Target

作用: 指定注解可以应用的程序元素类型 (Target Element)。

ElementType 枚举:

  • ElementType.TYPE: 可以应用于类、接口、枚举、注解。
  • ElementType.FIELD: 可以应用于字段。
  • ElementType.METHOD: 可以应用于方法。
  • ElementType.PARAMETER: 可以应用于方法参数。
  • ElementType.CONSTRUCTOR: 可以应用于构造方法。
  • ElementType.LOCAL_VARIABLE: 可以应用于局部变量。
  • ElementType.ANNOTATION_TYPE: 可以应用于注解。
  • ElementType.PACKAGE: 可以应用于包。
  • ElementType.TYPE_PARAMETER: 类型参数,since 1.8
  • ElementType.TYPE_USE: 使用类型的任何地方, since 1.8

示例:

@Target({ElementType.METHOD, ElementType.TYPE}) // 指定注解可以应用于方法和类
public @interface MyAnnotation {
    // ...
}

1.@Documented

作用: 指定该注解应该包含在 Javadoc 文档中。

示例:

@Documented // 指定该注解应该包含在 Javadoc 文档中
public @interface MyAnnotation {
    // ...
}

2.@Inherited

作用: 指定该注解可以被子类继承。

示例:

@Inherited // 指定该注解可以被子类继承
public @interface MyAnnotation {
    // ...
}

3.@Repeatable (Java 8+):

作用: 指定该注解可以在同一个程序元素上重复使用。

示例:

@Repeatable(Authorities.class)
public @interface Authority {
    String role();
}

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

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

三、内置注解 (Built-in Annotations)

Java 提供了一些内置注解,可以直接使用:

1.@Override

作用: 用于标记一个方法是重写 (Override) 了父类的方法。

用途:

  • 帮助编译器检查是否正确地重写了方法。 如果方法签名与父类方法不匹配,编译器会报错。
  • 提高代码可读性,明确表明该方法是重写了父类的方法。

示例:

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

class Dog extends Animal {
    @Override // 标记该方法重写了父类的 eat() 方法
    void eat() {
        System.out.println("Dog is eating.");
    }
}

2.@Deprecated

作用: 用于标记一个类、方法或字段已过时 (Deprecated),不建议使用。

用途:

  • 提醒开发者该类、方法或字段已经不推荐使用,可能会在将来的版本中被移除。
  • 可以提供替代方案的说明。

示例:

@Deprecated // 标记该方法已过时
public void oldMethod() {
    // ...
}

/**
 * @deprecated Use {@link #newMethod()} instead.
 */
@Deprecated
public void oldMethodWithComment(){
    //...
}

public void newMethod() {
    // ...
}

3.@SuppressWarnings

作用: 用于抑制编译器发出的警告。

用途:

  • 在某些情况下,编译器可能会发出一些不必要的警告,可以使用 @SuppressWarnings 注解来抑制这些警告。

取值:

  • all: 抑制所有警告。
  • boxing: 抑制与自动装箱/拆箱相关的警告。
  • deprecation: 抑制与使用了 @Deprecated 标记的类、方法或字段相关的警告。
  • unchecked: 抑制与未检查的类型转换相关的警告(例如,在使用原始类型时)。
  • unused: 抑制与未使用的变量相关的警告。
  • resource: 抑制与资源未关闭相关的警告。
  • 等等 (具体取决于编译器)。

示例:

@SuppressWarnings("unchecked") // 抑制类型转换警告
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0); // 编译器会发出 unchecked 类型转换警告

四、自定义注解 (Custom Annotations)

除了内置注解,你还可以根据自己的需求创建自定义注解。

定义注解:

  • 使用 @interface 关键字定义注解。
  • 指定元注解 (@Retention, @Target 等)。
  • 定义注解成员。

使用注解:

  • 在程序元素(类、方法、字段等)上使用自定义注解,并为注解成员赋值(如果需要)。

处理注解 (Annotation Processing):

  • 编译时处理: 可以使用注解处理器 (Annotation Processor) 在编译时处理注解,生成代码或配置文件。 例如,Lombok 使用注解处理器自动生成 getter/setter 方法。
  • 运行时处理: 可以使用反射 API 在运行时获取注解信息,并根据注解信息执行相应的逻辑。

五、使用场景 (Annotation Usage Scenarios)

注解在 Java 中有着广泛的应用,主要包括以下场景:

编译时检查:

  • 使用 @Override 注解进行方法重写检查。
  • 使用 @SuppressWarnings 注解抑制编译器警告。

代码生成:

  • Lombok 使用注解处理器自动生成 getter/setter 方法、构造方法、equals()/hashCode() 方法等,简化代码编写。
  • JPA 使用注解来映射类和数据库表,生成 SQL 语句。
  • Spring MVC 使用注解来映射请求 URL 和处理方法。

配置:

  • Spring 使用注解来配置 Bean、依赖注入、事务管理、AOP 等。
  • JAX-RS 使用注解来定义 RESTful Web 服务。

运行时行为修改:

  • 单元测试框架 (例如 JUnit, TestNG) 使用注解来标记测试方法。
  • 安全框架 (例如 Spring Security) 使用注解来进行权限控制。
  • 序列化框架 (例如 Jackson, Gson) 使用注解来控制序列化和反序列化过程。

六、代码示例 (自定义注解)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME) // 指定注解在运行时可用
@Target(ElementType.METHOD) // 指定注解可以应用于方法
public @interface MyAnnotation { // 定义一个自定义注解

    String name() default "Default Name"; // 成员变量,默认值Default Name
    int value();   // 成员变量

}

class MyClass {

    @MyAnnotation(name = "My Method", value = 100) // 使用注解并赋值
    public void myMethod() {
        System.out.println("My method is called.");
    }
}

public class AnnotationExample {

    public static void main(String[] args) throws Exception {
        Class<?> clazz = MyClass.class;
        Method method = clazz.getMethod("myMethod");

        if (method.isAnnotationPresent(MyAnnotation.class)) { // 判断方法是否使用了 MyAnnotation 注解
            MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); // 获取注解对象

            System.out.println("Annotation name: " + annotation.name()); // 获取 name 成员的值
            System.out.println("Annotation value: " + annotation.value()); // 获取 value 成员的值
        }
    }
}

总结

Java 注解是一种强大的元数据机制,它可以在代码中嵌入补充信息,并在编译时或运行时被处理。 理解注解的定义、元注解、内置注解、自定义注解以及使用场景,可以帮助你编写更简洁、更灵活、更易于维护的 Java 代码。 掌握注解,能让你更深入地理解各种框架和库的运作方式,并能够自定义 Spring Boot Starter等功能.

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot进行Web开发的实现

    SpringBoot进行Web开发的实现

    Spring Boot让我们可以快速构建项目并运行web应用,大大简化了Spring的复杂配置,本文主要介绍了SpringBoot进行Web开发的实现,感兴趣的可以了解一下
    2023-10-10
  • 深度解析Spring AI请求与响应机制的核心逻辑

    深度解析Spring AI请求与响应机制的核心逻辑

    我们在前面的两个章节中基本上对Spring Boot 3版本的新变化进行了全面的回顾,以确保在接下来研究Spring AI时能够避免任何潜在的问题,本文给大家介绍Spring AI请求与响应机制的核心逻辑,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Spring Boot项目集成UidGenerato的方法步骤

    Spring Boot项目集成UidGenerato的方法步骤

    这篇文章主要介绍了Spring Boot项目集成UidGenerato的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 详解Java如何改变字符串中的字符

    详解Java如何改变字符串中的字符

    这篇文章主要介绍了Java如何改变字符串中的字符,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • SpringBoot前后端分离跨域问题:状态码403拒绝访问解决办法

    SpringBoot前后端分离跨域问题:状态码403拒绝访问解决办法

    这篇文章主要给大家介绍了关于SpringBoot前后端分离跨域问题:状态码403拒绝访问的解决办法,403是被服务器拒绝了,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • 使用JAXBContext 设置xml节点属性

    使用JAXBContext 设置xml节点属性

    这篇文章主要介绍了使用JAXBContext 设置xml节点属性的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java CompletableFuture的使用详解

    Java CompletableFuture的使用详解

    这篇文章主要介绍了Java CompletableFuture的使用详解,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-03-03
  • Java 将Excel转为SVG的方法

    Java 将Excel转为SVG的方法

    本文以Java示例展示如何将Excel文档转为SVG格式。通过本文中的方法,在将Excel转为SVG时,如果sheet工作表中手动设置了分页,则将每个分页的内容单独保存为一个svg文件,如果sheet工作表中没有设置分页,则将Excel sheet表格中默认的分页范围保存为svg。
    2021-05-05
  • Java编程求二叉树的镜像两种方法介绍

    Java编程求二叉树的镜像两种方法介绍

    这篇文章主要介绍了Java编程求二叉树的镜像两种方法介绍,分享了两种方法,递归与非递归,每种方法又分别介绍了两种解决思路,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • 详解redis与spring的整合(使用缓存)

    详解redis与spring的整合(使用缓存)

    本篇文章主要介绍了redis与spring的整合(使用缓存),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03

最新评论