注解开发

注解不仅包含了元数据,它还可以作用于程序运行过程中、注解解释器可以通过注解决定程序的执行顺序
 
Java提供了三种内建注解
  1. @Override - 标注在方法上 , 表示该方法是用于重写 , 非重写则报错
  2. @Deprecated - 标注在方法上 , 表示该方法已过时 , 不推荐使用 , 但仍然是可以使用的
  3. @SuppressWarnings - 告诉编译器忽略特定的警告信息
 
创建自定义注解和创建一个接口类似 , 但是要在interface前面加上@符号
注解的定义有一些限制
  • 注解方法不能带参数
  • 注解方法的返回值类型可以是 : 基本类型 , String , Enums , Annotation 或者是这些类型的对应数组
以下面这个注解定义的为例
 1 @Documented//拥有这个注解的元素可以被javadoc文档化
 2 @Target(ElementType.METHOD)
 3 //该注解可以注解的程序元素返回,不添加则表示可以注解任何程序元素
 4 @Inherited//该注解类型被自动继承
 5 @Retention(RetentionPolicy.RUNTIME)
 6 //指明该注解被保留的时间长短
 7 public @interface InfoMethod {
 8      String author() default "sookie" ;
 9      String date();
10      int version() default 1;
11      String comments();
12 }

 

从中可以看出注解还具备一些特性
  • 注解方法可以有默认值
  • 注解本身能够包含元注解 , 元注解是可以被用来注解其他注解的
    ( 上述的Documented , Target , Inherited , Retention就是元注解 , 仅此4种 )
 
这里需要提一下的是 java.lang.annotation.Annotation 接口
它是所有注解类型都需要扩展的公共接口 , 但手工扩展该接口并不能定义注解
一个注解本身也相当于一个接口
其对象是一个代理类的对象 , 将在下面的反射解析注解中看到
 
注解使用
public class Test {
     @Override
     @InfoMethod(author= "22",comments="Main method",date="2016-02-04")
     //存在默认值的注解方法,使用时可以不传值,其余都要传值
     public String toString(){
           return "Overriden toString method" ;
     }
     
     @Deprecated
     @InfoMethod(author= "33",comments="Deprecated method",date="2016-02-16")
     public static void oldMethod (){
          System. out.println("该方法已过时" );
     }
     
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @InfoMethod(comments= "SuppressWarnings method",date="2016-02-16")
     public static void genericsTest(){
          List list = new ArrayList();
          list.add( "OK");
           oldMethod();
     }
}

 


注解的解析
 
使用Java的反射机制来解析类当中的注解
@Retention必须被设置为 RUNTIME , 否则注解信息在执行过程中将不可用
所以也就不能从中得到任何与注解有关的数据
 
public static void main(String[] args) throws Exception{
     
     Class<Test> cls = (Class<Test>) Test. class;
     for(Method method : cls.getDeclaredMethods()){
           //获取到该类中的所有方法(不包括继承的)并执行遍历
           if(method.isAnnotationPresent(InfoMethod.class)){
               //如果指定类型的注解存在于此元素上
               for(Annotation anno : method.getAnnotations()){
                   System.out.println(method.getName()+"方法上的注解有" +anno);
              }
               InfoMethod methodAnno = method.getAnnotation(InfoMethod.class);
               //获取到该方法上的InfoMethod注解对象
               System.out.println("--author:" +methodAnno.author());
               System.out.println("--date:" +methodAnno.date());
               System.out.println("--comments:" +methodAnno.comments());
              
          }
     }
}

 

执行结果如下
可以发现除了我们自定义的注解@InfoMethod之外
只有@Deprecated被获取到了
分别去找 @Override和@SuppressWarnings 的源代码可以发现 
 

他们的保留时间都不是 RUNTIME
  • SOURCE - 注解仅存在于源码中
  • CLASS - 注解会在class字节码文件中存在 , 但运行时无法获得
  • RUNTIME - 注解会在class字节码文件中存在 , 运行时可以通过反射获得
 
补充说明 : 
getAnnotations 方法在Field  Method  Class 类当中都存在
可以获取添加在属性  方法  类之上的注解 


posted @ 2017-02-03 17:35  日月追影俯河山  阅读(204)  评论(0编辑  收藏  举报
TOP