1.介绍
注解 Annotation
- 就是Java代码里的特殊标记,作用是让其他程序根据注解信息来决定什么是执行该程序
- 注解:注解可以在类上、构造器上、方法上、成员变量上、参数上等位置
自定义注解
/**
* 自定义注解
*/
public @interface MyTest1 {
String aaa();
boolean bbb() default true;
String[] ccc();
}
特殊属性名:value
- 如果注解中只有一个vlue属性,使用注解时,value名称可以不写
public @interface MyTest2 {
String value(); // 特殊属性
}
注解的原理
- 注解本质是一个接口,Java中所有的注解都是继承了Annotation接口的
- @注解(…): 其实就是一个实现类对象,实现了该注解以及Annotation接口
2.元注解
元注解
- 指的是:修饰注解的注解
- @Target 声明被修饰的注解在哪些位置使用
- 类,成员变量,成员方法,成员参数,构造器,局部变量
- @Retention 声明注解的保留周期
- SOURCE 只作用在源码阶段,字节码文件中不存在
- CLASS (默认值)保留到字节码文件阶段,运行阶段不存在
- RUNTIME (开发常用)一直保留到运行解阶段
3.注解的解析
什么是注解的解析
- 就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来
如何解析注解
- 指导思想:要解析谁上面的注解,就应该先拿到谁
- 比如要解析类上面的注解,则应该先获取该类的Class对象,在通过Class对象解析其上面的注解
- 比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解
- Class、Method、Field、Constructor 都实现了AnnotatedElement接口,都拥有解析注解的能力
案例
先定义注解MyTest4
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest4 {
String value();
double aaa() default 100;
String[] bbb();
}
在Demo类中定义test1方法,在类和方法上使用MyTest4的注解
@MyTest4(value = "蜘蛛精", aaa = 991, bbb = {"Java", "Python"})
public class Demo {
@MyTest4(value = "孙悟空", aaa = 22, bbb = {"HTML", "CSS"})
public void test1() {
}
}
在AnnotationTest3测试类上,解析Demo类中的全部注解
public class AnnotationTest3 {
@Test
public void parseClass() throws NoSuchMethodException {
// 1.先得到Class对象
Class demoClass = Demo.class;
// 2.解析类上的注解
// 判断类上是否包含了某个注解
if (demoClass.isAnnotationPresent(MyTest4.class)) {
MyTest4 myTest4 = (MyTest4) demoClass.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
// 3.解析方法上的注解
Method test1 = demoClass.getDeclaredMethod("test1");
if (test1.isAnnotationPresent(MyTest4.class)) {
MyTest4 myTest4 = test1.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
}
4.注解的应用场景
案例:模拟Junit框架
需求:定义若干个方法,只有加了MyTest注解,就会触发该方法执行
分析:
- 定义一个自定义注解MyTest,只能注解方法,存放范围是一直都在
- 定义若干个测试方法,部分方法加上@MyTest注解,部分方法不加
- 模拟Junit程序,可以触发加了@MyTest注解的方法执行
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
public class AnnotationTest4 {
public void test1() {
System.out.println("==test1==");
}
@MyTest
public void test2() {
System.out.println("==test2==");
}
public void test3() {
System.out.println("==test3==");
}
@MyTest
public void test4() {
System.out.println("==test4==");
}
public static void main(String[] args) throws Exception {
// 1.获取对象
Class annotationTest4Class = AnnotationTest4.class;
// 2.获取所有方法
Method[] methods = annotationTest4Class.getDeclaredMethods();
// 3.遍历所有方法
AnnotationTest4 annotationTest4 = new AnnotationTest4();
for (Method method : methods) {
// 4.判断如果存在MyTest注解
if (method.isAnnotationPresent(MyTest.class)) {
// 5.存在MyTest注解,执行该方法
method.invoke(annotationTest4);
}
}
}
}