Bootstrap

Java注解

三十七.注解

37.1 概述

Annotation表示注解,JDK1.5新特性

注解作用:对程序进行标准,可以给类增加额外的信息

注解是给编译器或JVM看的,编译器或JVM可以根据注解来完成对应的功能。

Java中已经存在的注解
@Override:表示方法的重写

@Deprecated:表示修饰的方法已过时

@SuppressWarnings("all"):压制警告
  

第三方框架中提供的注解:比如:Junit

  • @Test 表示运行测试方法

  • @Before 表示在Test之前运行,进行数据的初始化

  • @After 表示在Test之后运行,进行数据的还原

37.2 自定义注解

在这里插入图片描述

在这里插入图片描述

//自定义注解
public @interface AnnotationDemo1 {

    // 给name赋默认值。也可以不给默认值
    // public String name() default "aaaa";
    public String name();
    public int age();

}
================================
  //使用注解
@AnnotationDemo1(name = "aaaa",age=6666)
public class MyAnnotation {

    @AnnotationDemo1(name = "aaaa",age=6666)
    private String name;
    private int age;


    @AnnotationDemo1(name = "aaaa",age=6666)
    public void method01(){
        System.out.println("这是方法1");
    }
    public void method02(){
        System.out.println("这是方法2");
    }
}

特殊属性value:

​ 当注解中只有"一个属性",并且属性名是"value",使用注解时,可以省略value属性名

代码示例:

//注解的定义
public @interface Anno2 {
    public String value();

    public int age() default 23;
}

//注解的使用
@Anno2("123")
public class AnnoDemo2 {

    @Anno2("123")
    public void method(){

    }
}

37.3 元注解

元注解:注解注解的注解,即 可以写在注解上面的注解

@Target :指定注解能在哪里使用

@Retention :可以理解为保留时间(生命周期)

Target:

​ 作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。

​ 可使用的值定义在ElementType枚举类中,常用值如下

  • TYPE,类,接口
  • FIELD, 成员变量
  • METHOD, 成员方法
  • PARAMETER, 方法参数
  • CONSTRUCTOR, 构造方法
  • LOCAL_VARIABLE, 局部变量
@Target(ElementType.METHOD) //表示注解只能写在方法上
public @interface AnnotationDemo2 {

    // 给name赋默认值。也可以不给默认值
    // public String name() default "aaaa";
    public String name();
    public int age();
}
================================
  @AnnotationDemo2(name = "aaaa",age=6666)//此行报错
public class MyAnnotation2 {
  
    @AnnotationDemo2(name = "aaaa",age=6666)//此行报错
    private String name;
    private int age;

    @AnnotationDemo2(name = "aaaa",age=6666)
    public void method01(){
        System.out.println("这是方法1");
    }

}
Retention:

​ 作用:用来标识注解的生命周期(有效范围)

​ 可使用的值定义在RetentionPolicy枚举类中,常用值如下

  • SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
  • CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
  • RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo2 {

    // 给name赋默认值。也可以不给默认值
    // public String name() default "aaaa";
    public String name();
    public int age();
}

37.4 注解的解析

在这里插入图片描述

在这里插入图片描述

案例:模拟Junit框架

需求:

  • 定义若干个方法,只需要加了MyTest注解,就可以在启动时被触发执行

分析:

  • 定义一个自定义注解MyTest,只能注解方法,存活范围是一直都在的
  • 定义若干方法,只要有@MyTest注解的方法就能在启动时被触发执行,没有@MyTest注解的方法不能执行

代码实现:

//注解只能写在方法上
@Target(ElementType.METHOD)
// 表示注解在任何时期都存在
//如果写Source,只能在源码阶段存在,利用反射无法解析
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
========================================================
  public class MyTestDemo {

    //程序运行之后自动运行method01方法
    @MyTest
    public void method01(){
        System.out.println("这是方法1");
    }

    public void method02(){
        System.out.println("这是方法2");
    }
}

==========================================
  public class MyAnnoTest {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {

        // 1.获取MyTestDemo类的字节码文件对象
        Class<?> aClass = Class.forName("annotation.MyTestDemo");

        MyTestDemo mtd = new MyTestDemo();

        // 2.获取aClass对象中所有的方法
        Method[] methods = aClass.getDeclaredMethods();

        // 3.遍历得到每一个方法
        for (Method method : methods) {
            // 4.修改临时权限
            method.setAccessible(true);
            // 5.判断当前方法上有没有MyTest注解
            if(method.isAnnotationPresent(MyTest.class)){
                method.invoke(mtd);
            }
        }

    }
}
//运行结果:这是方法1
;