Java-元注解
如果某注解类A注解的对象也是一个注解类,那么注解类A即是一个元注解。
@Retention:定义注解的保留策略
package java.lang.annotation;
@Documented // 注解会被一直保留,包括虚拟机运行期间 @Retention(RetentionPolicy.RUNTIME) // 表明该注解类可以注解其他的注解类 // 当前注解类是元注解类 @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { /** * @return 注解的保留策略/注解的生命周期 */ RetentionPolicy value(); }
注解的保留策略全部定义在枚举类RetentionPolicy中。
package java.lang.annotation; // 注解的声明周期 public enum RetentionPolicy { /** * 注解仅保留在源码中,在java文件被编译成class文件的期间被丢弃。 */ SOURCE, /** * 注解仅保留在源码和class文件中,在class文件被加载到jvm的时候被丢弃。 */ CLASS, /** * 注解始终保留,代码运行期间可以通过反射来读取到该级别的注解。 */ RUNTIME }
@Target:定义注解类注解的目标类型
package java.lang.annotation; @Documented // 注解会被一直保留,包括虚拟机运行期间 @Retention(RetentionPolicy.RUNTIME) // 表明该注解类可以注解其他的注解类 // 当前注解类是元注解类 @Target(ElementType.ANNOTATION_TYPE) public @interface Target { /** * 返回该注解能注解的元素类型数组 */ ElementType[] value(); }
注解的目标类型全部定义在枚举类ElementType中。
package java.lang.annotation; public enum ElementType { // 可注解的目标类型:类、接口(包括注解)、枚举类 TYPE, // 可注解的目标类型:成员变量、枚举类常量 FIELD, // 可注解的目标类型:方法 METHOD, // 可注解的目标类型:方法参数 PARAMETER, // 可注解的目标类型:构造函数 CONSTRUCTOR, // 可注解的目标类型:本地变量 LOCAL_VARIABLE, // 可注解的目标类型:注解 ANNOTATION_TYPE, // 可注解的目标类型:包 // 注解包的代码是写在package-info.java文件中, // 一般需要手动创建,该文件存放在被注解的包路径下。 PACKAGE, /** * 可注解的目标类型:类型参数/泛型参数 * @since 1.8 */ TYPE_PARAMETER, /** * 可注解所有类型的目标 * @since 1.8 */ TYPE_USE }
@Document:说明在生成javadoc时将保留该注解
package java.lang.annotation;
@Documented // 表明该注解将会一直保留至虚拟机整个运行期间 @Retention(RetentionPolicy.RUNTIME) // 可以注解在注解元素上,标明这是一个元注解 @Target(ElementType.ANNOTATION_TYPE) public @interface Documented { }
@Inherited:定义子类可以从父类继承的注解
package java.lang.annotation; @Documented // 注解会被一直保留,包括虚拟机运行期间 @Retention(RetentionPolicy.RUNTIME) // 表明该注解类可以注解其他的注解类 // 当前注解类是元注解类 @Target(ElementType.ANNOTATION_TYPE) public @interface Inherited { }
@Inherited是元注解,注解的目标是注解,当然也包括元注解,但是什么意义都没有,纯属脱裤子放屁。
假设存在一个被@Inherited注解的注解InheritedAnnotation:
InheritedAnnotation注解的对象 |
子类(或子类的方法)是否能继承父类(或父类的方法) |
接口InterfaceB |
不能 |
类ClassA |
能 |
类ClassA中的一个方法FunctionA |
子类只要不复写方法FunctionA,子类就可以继承父类方法上的注解 |
接口InterfaceB中的一个抽象方法FunctionB |
实现接口的子类必然要复写方法,因此不能 |
@Repeatable:定义可多次注解同一目标的注解类
一般情况下,使用一个注解类A来注解目标E,注解类A只能注解一次目标E。如果需要注解类A对目标E注解多次,那么可以就可以使用@Repeatable来注解A。
package java.lang.annotation; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Repeatable { /** * 注解容器:容器中存放的元素也是注解 * @return 注解类型容器 */ Class<? extends Annotation> value(); }
示例:使用@Person多次注解Man类
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Persons { Person[] value(); } @Repeatable(Persons.class) public @interface Person{ String role() default ""; } @Person(role="CEO") @Person(role="husband") @Person(role="father") @Person(role="son") public class Man { String name=""; }