zoukankan      html  css  js  c++  java
  • 3、解析注解

    注解处理器

           何为解析注解?即通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。
    解析注解主要用到两个类库:
    1.1.  java.lang.annotation.Annotation
    Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。
    1.2. java.lang.reflect.AnnotatedElement
    AnnotatedElement 接口代表程序中可以接受注解的程序元素,是所有程序元素(Class、Method、Field、Package和Constructor)的父接口。获取该接口对象之后,即可以调用对象方法来访问Annotation信息,常用有如下几个:
             1. getAnnotations():返回该程序元素上存在的所有注解。
             2. isAnnotationPresent(annotation.class):判断该程序元素上是否包含指定类型的注解
             3. getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。
     

    2. 解析注解的代码例子

    定义一个注解如下:
     
    1. package jtzeng;  
    2. import java.lang.annotation.Documented;  
    3. import java.lang.annotation.ElementType;  
    4. import java.lang.annotation.Inherited;  
    5. import java.lang.annotation.Retention;  
    6. import java.lang.annotation.RetentionPolicy;  
    7. import java.lang.annotation.Target;  
    8. @Target({ElementType.METHOD,ElementType.TYPE})  
    9. @Retention(RetentionPolicy.RUNTIME)  
    10. @Inherited  
    11. @Documented  
    12. public @interface Description {   
    13.     String desc();  
    14.     String author() default "JTZeng";  
    15.     int age() default 21;  
    16. }   
    定义一个使用了注解的Test类:
     
    1. package jtzeng;  
    2. @Description(desc="this is ElementType.TYPE",author="JTZeng",age=21)  
    3. public class Test1 {  
    4.     @Description(desc="this is ElementType.METHOD",author="JTZeng",age=18)  
    5.     public void run(){  
    6.         System.out.println("I can run!");  
    7.     }  
    8. }  
    再编写一个解析类:
     
    1. package jtzeng;  
    2. import java.lang.annotation.Annotation;  
    3. import java.lang.reflect.Method;  
    4. public class ParseAnno {  
    5.     public static void main(String[] args) {  
    6.         try {  
    7.             /* 
    8.              * 1.使用类加载器加载类 
    9.              * Class.forName("类名字符串") (注意:类名字符串必须是全称,包名+类名) 
    10.              */  
    11.             Class c = Class.forName("jtzeng.Test1");  
    12.               
    13.             //2.判断类上是否存在注解,并获取类上面注解的实例  
    14.             if(c.isAnnotationPresent(Description.class)){  
    15.                 Description Description = (Description) c.getAnnotation(Description.class);  
    16.                 System.out.println(Description.desc());  
    17.                 System.out.println(Description.author());  
    18.                 System.out.println(Description.age());  
    19.             }  
    20.               
    21.             //3.判断方法上是否存在注解,并获取方法上面注解的实例  
    22.             Method[] ms = c.getMethods();  
    23.             for (Method method : ms) {  
    24.                 if(method.isAnnotationPresent(Description.class)){  
    25.                     Description Description = (Description)method.getAnnotation(Description.class);  
    26.                     System.out.println(Description.desc());  
    27.                     System.out.println(Description.author());  
    28.                     System.out.println(Description.age());  
    29.                 }  
    30.             }  
    31.             //另一种获取方法上的注解的解析方法  
    32.             for (Method method : ms) {  
    33.                 Annotation[] as = method.getAnnotations();  
    34.                 for (Annotation annotation : as) {  
    35.                     if(annotation instanceof Description){  
    36.                         System.out.println(((Description) annotation).desc());  
    37.                         System.out.println(((Description) annotation).author());  
    38.                         System.out.println(((Description) annotation).age());  
    39.                     }  
    40.                 }  
    41.             }  
    42.               
    43.         } catch (ClassNotFoundException e) {  
    44.             e.printStackTrace();  
    45.         }  
    46.     }  
    47. }  
    运行解析类,结果如下,有三部分,第一部分是类上的注解,第二、三部分是不同的方法解析方法上的注解:
     

    3.测试元注解@Retention

    如果把@Retention改为SOURCE或者CLASS,再次运行ParseAnno类:
              运行结果如下,什么也没有,这进一步说明了,只有设置为RUNTIME,才可以在运行时通过反射机制来获取注解信息,从而实现动态控制程序运行的逻辑。
     

    4. 测试元注解@Inherited

    创建一个接口和一个父类,并改写Test1类:
     
    1. package jtzeng;  
    2. @Description(desc = "this is Interface")    //因为注解Description中的author和age成员有默认值,所以可以省略  
    3. public interface Invalid {  
    4.     @Description(desc = "this is Interface method")  
    5.     public void print();  
    6. }  
    7.   
    8.   
    9. package jtzeng;  
    10. @Description(desc = "this is class")  
    11. public class Valid {  
    12.     @Description(desc = "this is class method")  
    13.     public void run(){  
    14.         System.out.println("注解继承只能在子类中有效,不能在接口中继承");  
    15.     }  
    16. }  
    17.   
    18.   
    19. package jtzeng;  
    20. public class Test1 extends Valid implements Invalid {  
    21.     @Override  
    22.     public void run(){  
    23.         System.out.println("覆盖父类的方法");  
    24.     }  
    25.     @Override  
    26.     public void print() {  
    27.         System.out.println("实现接口的方法");  
    28.     }  
    29. }  
    再一次运行ParseAnno解析类,输出结果如下,说明只能继承父类的注解,并且是类上的注解:
  • 相关阅读:
    UML图箭头关系
    使用 Python 编写 vim 插件
    linux grep命令
    gevent For the Working Python Developer
    坐标系旋转变换公式图解
    欲哭无泪的p-value = 0.051 | 做几次重复能得到较低的p-value
    RNA-seq要做几次生物学重复?找出来的100%都是真正的应答基因
    Strand Specific mRNA sequencing 之重要性与分析
    为什么二代测序的原始数据中会出现Read重复现象?
    DNA甲基化研究概述
  • 原文地址:https://www.cnblogs.com/jtlgb/p/8579764.html
Copyright © 2011-2022 走看看