Java 四种元注解(注解的注解)

前面我们介绍了注解的概念,也解释了什么是元数据。这篇博客,我们来介绍解释注解的元数据,元注解。Java中有四种元注解:@Retention,@Target,@Documented和@inherited. 接下来,我们一一来介绍这些注解。

  • @Retention注解:只能用于修饰一个Annotation定义,用于指定该Annotation的生命周期。@Retention包含一个RetentionPolicy类型的成员变量,使用@Retention注解时必须为该变量成员赋值。下面是这三种保留策略的说明:
  1. RetentionPolicy.SOURCE: 在源文件(.java文件),即源文件中保留,编译时期注解将被丢弃。
  2. RetentionPolicy.CLASS: 在class文件中有效,即.class文件中保留。当JVM解释.class字节码时,不会保留该注解。这是默认策略。
  3. 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类自动有了该注解。

你可能感兴趣的:(Java基础知识)