注解的相关概念
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(); }