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類自動有了該註解。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章