註解是跟多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 用於指明當前註解的生命週期,它的基本定義如下:
同樣的,它也有一個 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