Java注解、元注解、自定义注解定义及应用

1. 注解的定义与本质

注解(Annotation),在Java开发中,注解为我们提供了方法,可以在代码中添加信息,而这些信息可以被编译器、开发工具或运行时环境读取和处理,是主流框架不可或缺的组成部分。可以理解为代码的"标签"或"标记"。

  • 核心接口:java.lang.annotation.Annotaton
  • 使用位置:类或类成员上
  • 使用个数:一个或多个
  • 定义格式:public @interface 注解名{}

1.1 注解的作用

  1. 编译检查
  2. 代码生成 :用于生成辅助代码、配置文件等(如Lombok的@Data)等。
  3. 运行时处理 :在程序运行时,通过反射读取注解信息,动态改变程序行为(如Spring的@Autowired、JUnit的@Test)等。

1.2 内置注解示例

Java提供了一些内置注解,我们早已在不知不觉中使用了。

java 复制代码
// 重写父类方法
@Override
public String toString() {
    return "这是一个重写的方法";
}

2. 元注解(Meta-Annotation)

可以理解为是用来解释注解的注解;注解中以抽象方法的方式完成参数传递;传递的参数数据类型,根据抽象方法的返回值决定;如果没有默认值要求必须传值。

2.1 常用的元注解

① @Target 定义注解生效位置

应用:@Target(ElementType.METHOD)

枚举类ElementType 常见使用的作用范围
TYPE -- 类
FIELD -- 字段
CONSTRUCTOR -- 构造器
METHOD--方法

② @Retention 定义注解生效的时间

应用:@Retention(RetentionPolicy.SOURCE)

枚举类RetentionPolicy 常见使用的生效时间
SOURCE -- 源码时期
CLASS -- 字节码时期
RUNTIME -- 运行时期

③ @Documented 将注解编写到帮助文档中

④ @Inherited 当前注解可以被继承

3. 自定义注解

掌握了元注解,我们就可以定义自己的注解了。自定义注解使用@interface关键字,其本质是一个接口,继承java.lang.annotation.Annotation接口。自定义注解必须编写@Target、@Retention这两个注解。

应用:定义自定义注解,并在Student类中使用,实现获取到自定义注解中的值

3.1 定义自定义注解

java 复制代码
/**
 * 自定义注解必须写上@Target  @Retention
 */
 //定义注解作用范围为方法和构造器
@Target({ElementType.METHOD,ElementType.CONSTRUCTOR})
//定义注解生效为运行时期
@Retention(RetentionPolicy.RUNTIME)
public @interface DIYAnnotation {
    /*
        想要传递几个参数,就定义几个抽象方法
        如果注解中只有一个抽象方法,方法名一般都是value
     */
    String[] value();//没有默认值,必须传值

    boolean flag() default true;//有默认可以省略不传参
}

3.2 使用自定义注解

java 复制代码
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student {

    private String name;
    private int age;
    private String sex;

    //如果值传递一个参数,且是value是可以省略不写的,如果多个参数,必须标注参数名=值
    @DIYAnnotation(value= "aa",flag = false)
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

3.3 应用自定义注解

java 复制代码
    @Test
    public void getParamFromAnnotation() throws Exception {
        //获取字节码对象
        Class<Student> clazz = Student.class;
        //通过字节码对象获取构造器对象;构造器是指定类的,下面获取的构造器对象,会根据类去联想生成接收变量
        Constructor<Student> constructor = clazz.getConstructor(String.class, int.class);
        //API:isAnnotationPresent():判断构造器上是否使用了指定的注解
        if (constructor.isAnnotationPresent(DIYAnnotation.class)){
            //通过构造器对象,获取注解对象
            DIYAnnotation annotation = constructor.getAnnotation(DIYAnnotation.class);
            String[] values = annotation.value();
            System.out.println(Arrays.toString(values));
            boolean flag = annotation.flag();
            System.out.println(flag);
        }
    }
相关推荐
特立独行的猫A4 小时前
用仓颉语言 cj-tauri 框架,五分钟给娃做了个鸿蒙形近字游戏
java·后端·python
大可不必了8 小时前
03 函数定义和调用
开发语言·python
I_belong_to_jesus8 小时前
C++关于分支预测的优化1
开发语言·c++·算法
承渊政道9 小时前
【Python编程—从入门到实践】(记分与闯关:用Python+Pygame,打造越战越精彩的太空大战!)
开发语言·python·pycharm·游戏程序·pygame
爱学习的程序媛9 小时前
Python常用框架梳理
开发语言·后端·python·ai·web·后端框架·python框架
budingxiaomoli11 小时前
Spring统一功能处理
java·后端·spring
eggwyw11 小时前
Anaconda安装卸载的详细流程指南
开发语言·python
Flynn Liang12 小时前
可观测性与成本治理:一次对话的 17 个观测点
java·langchain·可观测性·micrometer·langchain4j·token 成本·llm 监控
金銀銅鐵13 小时前
带您看懂字节码指令(三):同一行加法,为什么有四种指令
java·jvm
another heaven15 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++