1. 注解的定义与本质
注解(Annotation),在Java开发中,注解为我们提供了方法,可以在代码中添加信息,而这些信息可以被编译器、开发工具或运行时环境读取和处理,是主流框架不可或缺的组成部分。可以理解为代码的"标签"或"标记"。
- 核心接口:
java.lang.annotation.Annotaton - 使用位置:类或类成员上
- 使用个数:一个或多个
- 定义格式:public @interface 注解名{}
1.1 注解的作用
- 编译检查
- 代码生成 :用于生成辅助代码、配置文件等(如Lombok的
@Data)等。 - 运行时处理 :在程序运行时,通过反射读取注解信息,动态改变程序行为(如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);
}
}