注解的相关概念
1.认识Annotation
JDK1.5开始,java增加了对元数据(即类的组成单元数据)的支持,也就是(Annotation)注解,它是代码里做的特殊标记,这些标记可以在编译,类加载,运行时在不改变原有逻辑的情况下,被读取,并执行相应的处理,通过使用Annotation,程序员可以在源文件中嵌入一些补充的信息,代码分析工具。开发工具和部署工具可以通过这些补充信息进行验证或者进行部署,Annotation类似于修饰符一样被使用,可以用于包,类,构造器方法,方法,成员变量,参数,局部变量的声明
2.系统自定义的Annotation
在JDK.1.5之后,在系统中提供了三个Annocation,分别是 @Override,@Deprecated,@SuppressWarnings
-
@Override
表示当前的方法定义将覆盖超类中的方法,如果你不小心拼写错误,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示。
例如:我们常见的toString方法,如果写错,这里会有提示
-
@Deprecated
表示的是一个方法已经过时了不再建议使用了,标记为已过时
例如:
如果进行调用的话:
-
@SuppressWarnings
表示关闭不当的编译器警告信息
例如:我们创建一个没有指定类型的list集合
这里会爆出黄色警告,加上注解后
警告消失。
3.自定义Annocation(注解应用需要三个步骤)
(1)编写注解(这里可以给变量添加默认值)
public @interface MyAnnotation {
// 定义变量
String name();
int age() default 2;// 给变量设置默认值
String[] eat();
Color color();
}
(2)在类上应用注解(有默认值的变量可以不用写,其他变量值必须要写)
@MyAnnotation(name = "欢欢", eat = {"猪肉", "牛肉"}, color = Color.GREEN)
class Dog {
private int age;
private String name;
private String[] eat;
private Color color;
public String[] getEat() {
return eat;
}
public void setEat(String[] eat) {
this.eat = eat;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public Dog(int age, String name) {
this.age = age;
this.name = name;
}
public Dog() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + '\'' +
", eat=" + Arrays.toString(eat) +
", color=" + color +
'}';
}
/**
* 这个注解表明此方法过时
*/
@Deprecated
public void getInfo() {
System.out.println("已经过时的方法");
}
}
这里用到了一个枚举类:
package com.lili.annotation;
/**
* @author: QiJingJing
* @create: 2021/7/16
*/
public enum Color {
/**
* 红色,绿色,蓝色
*/
RED, GREEN, YELLOW;
}
(3)对应用了注解的类进行反射操作的类(通过反射获取对象注解的值并给对象赋值)
@Test
public void test2() {
Class<Dog> dogClass = Dog.class;
// 获取类上应用的指定注解
MyAnnotation annotation = dogClass.getAnnotation(MyAnnotation.class);
// 获取注解上的变量值
int age = annotation.age();
Color color = annotation.color();
String name = annotation.name();
String[] eat = annotation.eat();
try {
Dog dog = dogClass.newInstance();
// 进行赋值
dog.setAge(age);
dog.setColor(color);
dog.setName(name);
dog.setEat(eat);
System.out.println(dog);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
运行如下:
4.Retention和RetentionPolicy注解
Annotation要想决定其作用的范围,通过@Retention指定,而Retention指定的范围由RetentionPolicy决定,RetentionPolicy三种范围,源码如下:
我们可以看到,@Retention注解的变量是RetentionPolicy类型的,我们不妨点进去查看:
是个枚举类,有三种对象供我们使用,
-
SOURCE :在java源文件中存在
-
CLASS :在java生成的class中存在
-
RUNTIME: 在java运行的时候存在;
5.@Target注解和@Documented注解
@Target注解表示的是一个Annotation的使用范围
范围 | 描述 |
---|---|
TYPE | 只能在类上或接口或枚举上使用 |
FIELD | 在成员变量中使用 |
METHOD | 在方法中使用 |
PARAMETER | 在参数上使用 |
CONSTRUCTOR | 在构造中使用 |
LOCAL_VARIABLE | 在局部变量中使用 |
ANNOTATION_TYPE | 在注解上使用 |
PACKAGE | 在包中使用 |
而@Documented注解表示在注解中使用,表示可生成带注释的文档。
因此,我们可以完善自定义注解如下:
package com.lili.annotation;
import java.lang.annotation.*;
/**
* 自定义注解
*
* @author 齐菁菁
*/
/*表示可生成带注释的文档*/
@Documented
// 表示该注解的作用范围在运行中存在
@Retention(RetentionPolicy.RUNTIME)
// 注解的应用范围(类型,属性,方法,构造器,参数,局部变量,包,注解)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
// 定义变量
String name();
int age() default 2;// 给变量设置默认值
String[] eat();
Color color();
}