Java_注解(21)

注解

注解在 JDK 1.5 时引入,可以加在类,方法,变量上,可以有属性,不同注解作用范围不同

一个注解由 Annotation,ElementType、RetentionPolicy 组成

1
2
3
4
5
6
public interface Annotation {
  boolean equals(Object obj);
  int hashCode();
  String toString();
  Class<? extends Annotation> annotationType();
}

ElementType 定义了注解可标注的对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public enum ElementType {
  TYPE,               //类、接口、枚举
  FIELD,              //字段
  METHOD,             //方法
  PARAMETER,          //参数
  CONSTRUCTOR,        //构造方法
  LOCAL_VARIABLE,     //局部变量
  ANNOTATION_TYPE,    //注释类型
  PACKAGE             //包
}

RetentionPolicy 定义了注解的作用范围

1
2
3
4
5
public enum RetentionPolicy {
  SOURCE,  //编译期间有效,编译完成即失效,例如 @Author @Since @See,javadoc生成.chm 
  CLASS,   //默认,作用于类对应的.class文件,例如 @Override,声明当前方法是重写的方法
  RUNTIME  //运行有效,例如 @Test,声明当前方法是测试方法,在JUnit包下定义
}

每个 Annotation 都会有唯一的 RetentionPolicy 属性、若干个 ElementType 属性

注解定义

定义一个名为 MyAnnotation 的注解,定义后即可在代码中使用 @MyAnnotation

1
2
3
4
5
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}

实现 java.lang.annotation.Annotation 接口与 implemented 实现普通接口不同,需要声明 @interface 来实现,通过 @interface 定义注解后,该注解就不能继承其他的注解或接口

@Documented 表示其标注的注解可以出现在 javadoc 中,没有 @Documented 则不出现

@Target 用来指定其标注的注解的 ElementType,这里指定为 TYPE,即表示 MyAnnotation 只能标注类、接口、枚举,没有@Target,则表示标注不受限制

@Retention 用来指定其标注的注解的运行策略 RetentionPolicy,这里指定为 RUNTIME,即表示 MyAnnotation 运行有效,没有@Retention,则默认 RetentionPolicy.CLASS

自定义注解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Test {
  public static void main(String[] args) throws Exception {
    //加载Print.class字节码中的方法,找到添加了@MyAnnotation注解的方法
    Class clazz = Class.forName("Print");
    Method[] mds = clazz.getMethods();
    for (Method md : mds) {
      //如果方法添加了注解就运行
      if (md.isAnnotationPresent(MyAnnotation.class)) {
        //获取MyAnnotation注解实例
        MyAnnotation myAn = md.getAnnotation(MyAnnotation.class);
        //获取MyAnnotation的值
        String value = myAn.value();
        //执行print方法
        md.invoke(new Print(), value); //aaa
      }
    }
  }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {
  //定义注解属性
  //属性类型 属性名称() default 默认值;
  String value() default "MyAnnotation";
  //属性支持基本类型、String、Class、Annotation、枚举、一维数组,不支持自定义类
}

class Print {
  @MyAnnotation("aaa")
  public void print(String value) {
    System.out.println(value);
  }
}

以上内容是玉山整理的笔记,如有错误还请指出