Java 四种元注解(注解的注解)
前面我们介绍了注解的概念,也解释了什么是元数据。这篇博客,我们来介绍解释注解的元数据,元注解。Java中有四种元注解:@Retention,@Target,@Documented和@inherited. 接下来,我们一一来介绍这些注解。
-
@Retention注解:只能用于修饰一个Annotation定义,用于指定该Annotation的生命周期。@Retention包含一个RetentionPolicy类型的成员变量,使用@Retention注解时必须为该变量成员赋值。下面是这三种保留策略的说明:
- RetentionPolicy.SOURCE: 在源文件(.java文件),即源文件中保留,编译时期注解将被丢弃。
- RetentionPolicy.CLASS: 在class文件中有效,即.class文件中保留。当JVM解释.class字节码时,不会保留该注解。这是默认策略。
- RetentionPolicy.RUNTIME: 在运行时有效,即运行时保留。当运行Java程序时,JVM会保留注解,Java程序可以通过反射获取该注解。
-
自定义注解:
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String [] values(); int number(); }
-
演示@Retention(value = RetentionPolicy.RUNTIME)的使用:
import org.junit.jupiter.api.Test; import java.lang.annotation.Annotation; public class AnnotationTest1 { @Test @MyAnnotation(values = { "value1", "value2"}, number = 10) public void test1(){ } @Test public void test2() throws NoSuchMethodException { //类Class的对象,表示到加载内存里的运行时类(AnnotationTest1) Class clazz = AnnotationTest1.class; //通过方法类对象实例调用getAnnotations()去获取注解数组 Annotation [] annotations = clazz.getMethod("test1", null).getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation.toString()); } } }
-
输出:
@org.junit.jupiter.api.Test() @EnumAndAnnotation.MyAnnotation(values=[value1, value2], number=10)
我们可以看到注解到test1方法的两个注解都被打印了出来。说明不仅我们自定义的@MyAnnotation被@Retention注解了,而且策略为RetentionPolicy.RUNTIME,并且@Test注解也是相同的情况。
-
@Target注解:用于修饰Annotation定义,指定被修饰的Annotation能用于修饰哪些程序元素。@Target包含一个数组成员变量,该值如下(Java 8版本): TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, TYPE_USE 顾名思义,由名称可知,数组中包含哪些值,就可以注解到对应的地方。 @Documented注解: 用于指定被该元注解修饰的Annotation类将被javadoc工具提取成文档。默认情况下,javadoc是不包括注解,@Documented注解必须要和策略为RUNTIME的@Retention注解一起使用。 @Inherited注解:被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。 @Inherited注解的实例代码:
import java.lang.annotation.*; @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE,ElementType.METHOD}) public @interface MyAnnotation { String [] values(); int number(); }
package EnumAndAnnotation; @MyAnnotation(values = { "value"}, number = 10) public class Person { } class Student extends Person{ }
@Test public void test3(){ Class clazz = Student.class; Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation.toString()); } }
-
输出:
@EnumAndAnnotation.MyAnnotation(values=[value], number=10)
-
即使Student类没有显示地被注解@MyAnnotation,但是它的父类Person被注解,而且@MyAnnotation被@Inherited注解,因此Student类自动有了该注解。
下一篇:
可以边玩游戏边学编程的手游盘点