当前位置: 代码网 > it编程>编程语言>Java > Java注解(Annotations)的定义和使用详解

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

2025年03月11日 Java 我要评论
java 注解(annotations)是 java 5 引入的一种元数据(metadata),它提供了一种在源代码中嵌入补充信息的方式,这些信息可以被编译器、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等功能.

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com