一、概念
注解,也叫元数据。一种代码级别的说明,是JDK1.5以后的新特性。是说明给程序看的(注释是说明给程序员看的)
二、功能
- 编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
- 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
- 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【例如:override】
三、编写文档
1.我们新建一个类,然后完成下面的代码
package 注解;
/**
*注解演示
* @author 蓝月
* @since 1.5
* @version 2.0
*/
public class Note {
/**
*
* 计算两数的差
* @param a int
* @param b int
* @return 两数之差*/
public int sub(int a, int b){
return a - b;
}
}
2.然后使用如下命令生成帮助文档
javadoc Note.java
3.查看帮助文档
四、编译检测
系统自带了很多注解,比如 @override、@since、@After、@Before、@Deprecated(标注过时)、@SuppressWarnings()(压制警告)等等,这里就不介绍了
小知识点:
javap [xxx.class] ===> 反编译.class文件
五、代码分析——自定义注解
注解本质上是一个接口,继承自 java.lang.annotation.Annotation 接口。既然注解是一个接口,那就意味着接口可以定义啥,注解也可以定义啥
1.注解可定义的方法返回值类型
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
2.注意事项
①使用注解时,必须给注解的属性赋值。在定义注解的时候可以使用关键字 default 给注解属性赋初始值
②注解可以有注解属性。那么如果实现类想要使用该注解时,需要使用 xxx = @yyy
③给数组赋值时,需要使用 {} 赋值
④给枚举取值时,需要使用[枚举类名].[枚举值]赋值
枚举类:
public enum MyColor {
RED, GREEN, BLUE
}
注解类:
public @interface myAnno {
public abstract String initDate() default "2020-06-13";
public abstract int initVersion();
public abstract Override myOverride();
public abstract double[] options();
public abstract MyColor back();
}
实现类:
@myAnno(initVersion = 1, myOverride = @Override, options = {1.0, 2.0, 3.0}, back = MyColor.RED)
public class Realize {
}
3.元注解
①什么是元注解
用于描述注解的注解
②元注解类型
@Target ===> 用于描述注解能够作用的位置
取值:
ElementType.TYPE ===> 可以作用于类上
ElementType.METHOD ===> 可以作用于方法上
ElementType.FIELD ===> 可以作用于属性上
@Retention ===> 用于描述注解能够保留的阶段
取值:
RetentionPolicy.SOURCE ===> 作用于源码阶段
RetentionPolicy.CLASS ===> 作用于类对象阶段
RetentionPolicy.RUNTIME ===> 作用于运行时阶段
@Documented ===> 用于描述注解是否被抽取到API文档中
@Inherited ===> 用于描述注解是否被子类继承
六、使用(解析)注解
1.编写注解类
package com.learn;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//声明注解作用于类
@Target(value = {ElementType.TYPE})
//声明注解作用于程序运行时
@Retention(RetentionPolicy.RUNTIME)
public @interface MyPet {
//指明运行哪个类
public abstract String pet();
//指明运行哪个方法
public abstract String action();
}
2.编写工具类Dog、Cat
package com.learn;
public class Dog {
public void eat(){
System.out.printf("二哈在吃饭");
}
}
package com.learn;
public class Cat {
public void eat(){
System.out.printf("波斯猫在吃饭");
}
}
3.编写实现类
package com.learn;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@MyPet(pet = "com.learn.Cat", action = "eat")
public class Realize {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//获取类字节码文件对象
Class<Realize> cla = Realize.class;
//获取注解对象
//内存中生成了一个该注解接口的子类实现对象
MyPet myPet = cla.getAnnotation(MyPet.class);
//得到注解的各个参数值
String pet = myPet.pet();
String action = myPet.action();
//加载注解标识的类和方法
Class aCla = Class.forName(pet);
Method method = aCla.getMethod(action);
//根据类实例化对象
Object obj = aCla.newInstance();
//执行指定类的指定方法
method.invoke(obj);
}
}