如何自定義一個註解並獲取註解

註解是跟多java 架構經常用到的,那如何自己定義一個註解,今天我們學習註解的定義和使用。

所有的註解類型都繼承自這個普通的接口(Annotation)。

元註解

『元註解』是用於修飾註解的註解

通常有以下幾種

  • @Target:註解的作用目標
  • @Retention:註解的生命週期
  • @Documented:註解是否應當被包含在 JavaDoc 文檔中
  • @Inherited:是否允許子類繼承該註解

其中,@Target 用於指明被修飾的註解最終可以作用的目標是誰,也就是指明,你的註解到底是用來修飾方法的?修飾類的?還是用來修飾字段屬性的。

我們可以通過以下的方式來爲這個 value 傳值:

@Target(value = {ElementType.FIELD})

被這個 @Target 註解修飾的註解將只能作用在成員字段上,不能用於修飾方法或者類。其中,ElementType 是一個枚舉類型,有以下一些值:

  • ElementType.TYPE:允許被修飾的註解作用在類、接口和枚舉上
  • ElementType.FIELD:允許作用在屬性字段上
  • ElementType.METHOD:允許作用在方法上
  • ElementType.PARAMETER:允許作用在方法參數上
  • ElementType.CONSTRUCTOR:允許作用在構造器上
  • ElementType.LOCAL_VARIABLE:允許作用在本地局部變量上
  • ElementType.ANNOTATION_TYPE:允許作用在註解上
  • ElementType.PACKAGE:允許作用在包上

@Retention 用於指明當前註解的生命週期,它的基本定義如下:

image

同樣的,它也有一個 value 屬性:

@Retention(value = RetentionPolicy.RUNTIME

這裏的 RetentionPolicy 依然是一個枚舉類型,它有以下幾個枚舉值可取:

  • RetentionPolicy.SOURCE:當前註解編譯期可見,不會寫入 class 文件
  • RetentionPolicy.CLASS:類加載階段丟棄,會寫入 class 文件
  • RetentionPolicy.RUNTIME:永久保存,可以反射獲取

@Retention 註解指定了被修飾的註解的生命週期,一種是只能在編譯期可見,編譯後會被丟棄,一種會被編譯器編譯進 class 文件中,無論是類或是方法,乃至字段,他們都是有屬性表的,而 JAVA 虛擬機也定義了幾種註解屬性表用於存儲註解信息,但是這種可見性不能帶到方法區,類加載時會予以丟棄,最後一種則是永久存在的可見性。

剩下兩種類型的註解我們日常用的不多,也比較簡單,這裏不再詳細的進行介紹了,你只需要知道他們各自的作用即可。@Documented 註解修飾的註解,當我們執行 JavaDoc 文檔打包時會被保存進 doc 文檔,反之將在打包時丟棄。@Inherited 註解修飾的註解是具有可繼承性的,也就說我們的註解修飾了一個類,而該類的子類將自動繼承父類的該註解。

現在我們來自己定義一個註解類,目的是用它來標記某些字段。

@Documented
@Retention(RetentionPolicy.RUNTIME) //註釋由編譯器記錄在類文件中,並由*在運行時由VM保留,因此可以通過反射方式讀取它們
@Target(ElementType.FIELD) //  字段聲明(包括枚舉常量)
public @interface AnTest {
    int number();
}

現在我們找個類來應用下:

public class TestMode {
    @AnTest(number = 3)

    private int age;
    @AnTest(number = 2)

    String name;

    @AnTest(number = 1)

    int length;
    public TestMode() {
        if (false) {
        }
    }

    public TestMode(int age, String name, int length) {
        this.age = age;
        this.name = name;
        this.length = length;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "TestMode{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", length=" + length +
                '}';
    }
}

測試類:

public static void main(String args[]) {
    TestMode testMode = new TestMode(30, "明", 170);

    Class cla = testMode.getClass();

    Field[] fields = cla.getDeclaredFields();
    for (Field field : fields) {
        AnTest anTest = field.getAnnotation(AnTest.class);
        System.out.println(field.getName() +":自定義註解 :"+ anTest.number());
    }
}

結果:

age:自定義註解 :3
name:自定義註解 :2
length:自定義註解 :1

這樣我們就通過反射獲取到了我們自定義的註解。

參考:

https://blog.csdn.net/HaHa_Sir/article/details/81331437

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章