java注解
1. 概述
首先,注解(Annotation)是一个接口,程序可以通过反射来获取指定程序元素的java.lang.annotation.Annotation对象。然后通过这个 对象来取得注解里的元数据。
只有通过某种配套的工具对注解中的信息进行访问和处理,注解才会影响程序的运行(在程序运行时起到一定的作用),否则,注解不会影响程序 的运行。访问和处理注解的工具统称为 APT(Annotation Processing Tool).
2. Annotation 架构
2.1 概述
“每 1 个 Annotation” 都与 “1 个 RetentionPolicy” 关联,并且与 “1~n 个 ElementType” 关联。可以通俗的理解为:每 1 个 Annotation 对象,都会有唯一的 RetentionPolicy 属性;至于 ElementType 属性,则有 1~n 个。
2.2 ElementType
ElementType 是 Enum 枚举类型,它用来指定 Annotation 的类型。每1个 Annotation 都与 1~n 个 ElementType关联。
当 Annotation 与某个 ElementType 关联时,就意味着:Annotation有了某种用途。
例如,若一个 Annotation 对象是 METHOD 类型,则该 Annotation 只能用来修饰方法。
2.3 RetentionPolicy
RetentionPolicy 是 Enum 枚举类型,它用来指定 Annotation 的策略。通俗点说,就是不同 RetentionPolicy 类型的 Annotation 的作用域不同。每 1 个 Annotation" 都与 "1 个 RetentionPolicy 关联。
-
若 Annotation 的类型为 SOURCE,则意味着:Annotation 仅存在于编译器处理期间,编译器处理完之后,该 Annotation 就没用了。例如," @Override" 标志就是一个 Annotation。当它修饰一个方法的时候,就意味着该方法覆盖父类的方法;并且在编 译期间会进行语法检查!编译器处理完后,"@Override" 就没有任何作用了。
-
若 Annotation 的类型为 CLASS,则意味着:编译器将 Annotation 存储于类对应的 .class 文件中,它是 Annotation 的默认行为。
-
若 Annotation 的类型为 RUNTIME,则意味着:编译器将 Annotation 存储于 class 文件中,并且可由JVM读入。
3. JDK的元注解
3.1 概述:
想要定义注解,我们必须依靠JDK的元注解
JDK在java.lang.annotation 下提供了6个 Meta注解(元注解),其中5个注解都用于修饰其他注解定义,只有@Repeatable 是专门定义java8新增的重复注解。这里只学习四个常用的注解。
-
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
-
@Documented - 标记这些注解是否包含在用户文档中。
-
@Target - 标记这个注解应该是哪种 Java 成员。
-
@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
-
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
3.2 @Retention
只能用于修饰注解定义的,用于制定被修饰的注解,可以保留多长时间。他有三个值:
-
RetentionPolicy.SOURCE: 注解只保留在源代码中,编译器直接丢弃这种注解。
-
RetentionPolicy.CLASS:编译器把注解记录在class文件中,当运行程序时,JVM不可获取注解信息,这是默认值。
-
RetentionPolicy.RUNTIME:编译器将注解记录在class文件中,当运行Java程序时,JVM可以获取注解信息,程序可以通过反射获取该注解信息。
举例:@Retention(RetentionPolicy.RUNTIME) / @Retention(value = RetentionPolicy.RUNTIME)
3.3 @Target
也只能修饰注解定义,它用于指定被修饰的注解能用于修饰哪些程 序单元。它也包含一个名value的成员变量,该成员变量的值只能是以下几个
-
ElementType.ANNOTATION:指定该策略的注解只能修饰注解。
-
ElementType.CONSTRUCTOR:指定该策略的注解只能修饰构造器
-
ElementType.FIELD:指定该策略的注解只能修饰成员变量
-
ElementType.LOCAL_VARIABLE:指定该策略的注解只能修饰局部变量
-
ElementType.METHOD:指定该策略的注解只能修饰方法定义
-
ElementType.PACKAGE:指定该策略的注解只能修饰包定义
-
ElementType.PARAMETER:指定该策略的注解只能修饰参数
-
ElementType.TYPE:指定该策略的注解只能修饰类,接口(包括注解类型)或枚举类
举例:@Target(ElementType.METHOD)
3.4 @Documented
用于指定该元注解修饰的注解类将被javadoc工具提取成文档,如果定义注解类时使用了该修饰,则所有使用该注解修饰的程序元素的API文档中,将会包含该注解说明。
3.5 @Inherited
例子
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
该元注解指定被它修饰的注解将具有继承性。比如某个类使用了某个注解,该类的子类将自动被这个注解修饰
3.6 使用JDK的元注解创建自己的注解
例子
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
}
定义注解时,要使用 @interface关键字,意味着它实现了 java.lang.annotation.Annotation 接口。