目录
一、自定义注解
自定义注解格式:
//@interface 注解名
@interface MyTest{
/**
* 注解属性
* 属性适用的数据类型:
* int,short,long,double,byte,char,boolean,float,String,Class
* 以上类型的数组形式都支持
*
* */
//注解可以有属性,属性名必须带()
String name() default "test";
int[] ids();
}
注解使用:
public class Test {
@MyTest(ids = {1,2})
public void method1(){
}
}
二、元注解
元注解使用:
/***
* 元注解是sun公司提供的。
* 元注解是用在自定义注解上的注解。
* 元注解是用来注解自定义注解的。
*
* 元注解有两个:
* @Target:约束自定义注解只能在哪些地方使用,
* -- 但是默认的注解可以在类,方法,构造器,成员变量,... 使用。
*
* @Retention:申明注解的生命周期
* -- 申明注解的作用范围:编译时,运行时。
*
* @Target
* * 作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。
* * 可使用的值定义在ElementType枚举类中,常用值如下
* TYPE,类,接口
* FIELD, 成员变量
* METHOD, 成员方法
* PARAMETER, 方法参数
* CONSTRUCTOR, 构造器
* LOCAL_VARIABLE, 局部变量
*
* @Retention
* 作用:用来标识注解的生命周期(有效存活范围)
* * 可使用的值定义在RetentionPolicy枚举类中,常用值如下
* * SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
* * CLASS: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
* * RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
* 小结:
* @Target约束自定义注解可以标记的范围。
* @Retention用来约束自定义注解的存活范围。
*/
@Target({ElementType.TYPE,ElementType.METHOD}) //只在类和方法上使用
@Retention(RetentionPolicy.RUNTIME) //一直存活
@interface MyTest{
}
三、解析注解
模拟实现Junit注解
/***
* 我们会使用注解注释一个类的成分,那么就设计到要解析出这些注解的数据。
* 开发中经常要知道一个类的成分上面到底有哪些注解,注解有哪些属性数据,这都需要进行注解的解析。
*
* 与注解解析相关的接口
* 1. Annotation: 注解类型,该类是所有注解的父类。注解都是一个Annotation的对象
* 2. AnnotatedElement:该接口定义了与注解解析相关的解析方法
* 所有的类成分Class, Method , Field , Constructor:都实现了AnnotatedElement接口
* 他们都拥有解析注解的能力:
* a.Annotation[] getDeclaredAnnotations()
* 获得当前对象上使用的所有注解,返回注解数组。
* b.T getDeclaredAnnotation(Class<T> annotationClass)
* 根据注解类型获得对应注解对象
* c.boolean isAnnotationPresent(Class<Annotation> annotationClass)
* 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false
*
* 解析注解数据的原理
* * 注解在哪个成分上,我们就先拿哪个成分对象。
* * 比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解
* * 比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
* * 比如注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解
*/
/*******自定义一个注解*******/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTest{
}
public class Test{
@MyTest
public void test1(){
System.out.println("=====test1=====");
}
public void test2(){
System.out.println("====test2====");
}
//用main方法入口代替IDEA菜单执行按钮
public static void main(String[] args) throws Exception {
//创建一个实例对象
Test test = new Test();
//得到字节码class对象
Class clazz = Test.class;
//通过反射获取该类的所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//判断当前Method是否使用了指定的注解
if(method.isAnnotationPresent(MyTest.class)){
method.invoke(test);
}
}
}
}
执行main方法只有加了@MyTest注解的方法调用了
执行输出结果:
”=====test1====="