注解

注解可以在一些使用场景中代替配置文件的功能,实现轻量级的配置。

注解的开发使用流程:定义注解-->反射注解->使用注解

自定义注解:  

  1、基本的注解定义方式:
    public @interface 注解名称{

        // 定义体
    }
  2、可以使用源注解修饰:用于修饰注解的注解被称为源注解
    @Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD}) ------被描述的注解可以用在什么地方

        ElementType:
          ANNOTATION_TYPE 注释类型声明
          CONSTRUCTOR构造方法声明
          FIELD 字段声明(包括枚举常量)
          LOCAL_VARIABLE 局部变量声明
          METHOD 方法声明
          PACKAGE 包声明
          PARAMETER 参数声明
          TYPE 类、接口(包括注释类型)或枚举声明

    @Retention(RetentionPolicy.SOURCE/CLASS/RUNTIME)  -----  该Annotation被保留的时间长短

        RetentionPolicy.SOURCE:源码级别,给编译器看的;编译器编译后直接丢弃这种策略的注解。

        RetentionPolicy.CLASS:编译器编译后会保留这种策略的注解,生成的.class文件中保留该类注解,当运行Java程序时,JVM不会保留该类型的注解(给类加载器看的,在类加载时做一些引导的操作)

        RetentionPolicy.RUNTIME:编译->类加载->JVM运行。编译器将把注解记录到.class字节码文件中。当运行Java程序时,JVM会保留该类型的注解。程序可以通过反射获取该注解。(用的最多)。

    @Documented:用于指定被该注解(Anno1)修饰的类(Student)将被javadoc工具提取成文档中带有注解的使用信息。
    
  3、注解的属性
    A.注解中定义属性和接口中定义方法类似,修饰符(如public)缺省时默认就是public,所以public使用与否都是一样的。

      B.String name();在未指定默认值时,使用该注解的地方必须为name属性赋值,否则编译错误。如果想实现使用注解时可以为该属性赋值,也可不赋值,需要在定义属性时人为的指定一个默认值。String name() default "";

      C.注解中的属性类型是有要求的,可以是八种基本数据类型,可以是枚举类型、Class类型等,以及以上类型的“一维”数组
      比如:String[] likes() default {};
      在注解使用时,如果数组类型的属性的值是一个值得话,赋值时可以把“{}”省略掉。@Anno1(name="zs",likes="fb")

      D.存在一个特殊的属性:value,如果只为该属性赋值,value=可以省略;
      但是如果为注解中多个属性同时赋值的话,value=是不可以省

 

反射注解:

  只有运行时级别的注解才可以被反射。故需要反射该注解需要在定义注解时加上:@Retention(RetentionPolicy.RUNTIME)

    JDK中提供了接口AnnotatedElement中,提供反射注解相关的方法:

      1.<T extends Annotation> T getAnnotation(Class<T> annotationClass) ----- 获取注解。如果存在该元素的指定类型的注解,则返回这个注解,否则返回 null。

      2.Annotation[] getAnnotations() ------ 返回此元素上存在的所有注解。

      3.Annotation[] getDeclaredAnnotations() ------ 返回直接存在于此元素上的所有注解。

      4.boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) ------如果指定类型的注解存在于此元素上,则返回 true,否则返回 false。

 

注意:注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null;

 1 // 定义一个 PoliceLevel 注解 
 2 @Target(ElementType.TYPE)
 3 @Retention(RetentionPolicy.RUNTIME)
 4 public @interface PoliceLevel {
 5 
 6     //这是属性的定义不是方法的定义。 
 7     // 若先给了属性一个默认值时在用注解时就可以不用赋值当然也可以赋值
 8     String level() default "";  
    int le() default 1;
 9 10 }

使用注解和反射注解:

 1 package cn.tedu.anno;
 2 public class Police {
 3     public void getMoney(){
 4         System.out.println("敬个礼,您违章了,罚款200...");
 5     }
 6     public static void main(String[] args) {
 7         Police pc = new Police();
 8         pc.getMoney();
 9         //判断当前类中有没有PoloceLevel这个注解--若有返回true,否则反之
10         if(pc.getClass().isAnnotationPresent(PoliceLevel.class)){
11             //真警察   ---- 获取当前类上的注解
12             PoliceLevel pl = pc.getClass().getAnnotation(PoliceLevel.class);
13             String level = pl.level();
14             if("协警".equals(level)){
15                 System.out.println("哥们抽个烟,偷摸给你50...放我走吧...");
16             }else if("交警".equals(level)){
17                 System.out.println("给200,发票给我,走人。。。");
18             }else if("大队长".equals(level)){
19                 System.out.println("哥们抽包烟,给我开一个免罚金牌可好...");
20             }
21         }else{
22             //假的
23             System.out.println("揍一顿,送警察局。。。");
24             
25         }
26     }
27 } 

 

posted @ 2017-06-14 18:15  大大大圣  阅读(250)  评论(0编辑  收藏  举报