自定義Annotation(二)

諸惡莫作,衆善奉行,自淨其意,是諸佛教

勸諸君,多行善事積福報,莫作惡

上一章簡單介紹了Java的自帶註解Annotation(一),如果沒有看過,請觀看上一章

註解Annotation 很強大,很重要,是不是想要自己能夠編寫註解呢?

接下來,我們就可以嘗試編寫簡單的註解了。

本文參考菜鳥編程文章: Java 註解(Annotation)

一. Annotation 架構簡單瞭解

一.一 主要三大類

一.一.一 註解類 Annotation

package java.lang.annotation;

/**
 * @since   1.5
 */
public interface Annotation {
   
    boolean equals(Object obj);

  
    int hashCode();

	 toString();

    Class<? extends Annotation> annotationType();
}

是最原始的那個註解類。

一.一.二 作用類型 ElementType

package java.lang.annotation;

public enum ElementType {
    TYPE,               /* 類、接口(包括註釋類型)或枚舉聲明  */

    FIELD,              /* 字段聲明(包括枚舉常量)  */

    METHOD,             /* 方法聲明  */

    PARAMETER,          /* 參數聲明  */

    CONSTRUCTOR,        /* 構造方法聲明  */

    LOCAL_VARIABLE,     /* 局部變量聲明  */

    ANNOTATION_TYPE,    /* 註釋類型聲明  */

    PACKAGE             /* 包聲明  */
}

是一個枚舉,定義 註解的放置範圍。

一.一.三 保留策略 RetentionPolicy

package java.lang.annotation;
public enum RetentionPolicy {
    SOURCE,            /* Annotation信息僅存在於編譯器處理期間,編譯器處理完之後就沒有該Annotation信息了  */

    CLASS,             /* 編譯器將Annotation存儲於類對應的.class文件中。默認行爲  */

    RUNTIME            /* 編譯器將Annotation存儲於class文件中,並且可由JVM讀入 */
}

一.二 架構圖

有圖片

Annotation 與 RetentionPolicy 是一對一的關係,與 ElementType 是一對多的關係。

Override,Deprecated 等都是 Annotation的子類。

一.三 內置子類作用

(引用於菜鳥編程)

Java 定義了一套註解,共有 7 個,3 個在 java.lang 中,剩下 4 個在 java.lang.annotation 中。

作用在代碼的註解是

  • @Override - 檢查該方法是否是重寫方法。如果發現其父類,或者是引用的接口中並沒有該方法時,會報編譯錯誤。
  • @Deprecated - 標記過時方法。如果使用該方法,會報編譯警告。
  • @SuppressWarnings - 指示編譯器去忽略註解中聲明的警告。

作用在其他註解的註解(或者說 元註解)是:

  • @Retention - 標識這個註解怎麼保存,是隻在代碼中,還是編入class文件中,或者是在運行時可以通過反射訪問。
  • @Documented - 標記這些註解是否包含在用戶文檔中。
  • @Target - 標記這個註解應該是哪種 Java 成員。
  • @Inherited - 標記這個註解是繼承於哪個註解類(默認 註解並沒有繼承於任何子類)

老蝴蝶注:這個在創建新的註解時,非常有用。

從 Java 7 開始,額外添加了 3 個註解:

  • @SafeVarargs - Java 7 開始支持,忽略任何使用參數爲泛型變量的方法或構造函數調用產生的警告。
  • @FunctionalInterface - Java 8 開始支持,標識一個匿名函數或函數式接口。
  • @Repeatable - Java 8 開始支持,標識某註解可以在同一個聲明上使用多次。

老蝴蝶注:函數式編程時用的。

二. 創建簡單註解 @interface

創建註解,就像創建類,接口一樣簡單,只不是 類是 Class, 接口是 interface, 而註解是 @interface.
注意,是小寫,前面有一個 @

註解裏面,只有屬性, 沒有方法。 @interface 就表示實現了 java.lang.annotation.Annotation 接口。

二.一 創建簡單的註解

創建表 註解 Table

//創建表註解 
public @interface Table {


}

創建 Id 主鍵註解

public @interface Id {
    
}

創建 Column 列註解

public @interface Column {


}

在使用的時候, @Table, @Id, @Column 即可。

二.二 使用 註解

先創建一個簡單的pojo, Person ,裏面有 id,name,sex,age,desc 五個基本的屬性, 並且有相應的構造和 setter,getter方法。

@Table
public class Person implements Serializable {

    @Id
    private int id;
    @Column
    private  String name;
    @Column
    private  char sex;
    @Column
    private int age;
    @Column
    private String desc;

}

三. 添加元註解,表明註解的位置

可以添加四個元註解, @Retention, @Documented, @Target, @Inherited

可以用這四個元註解,來爲自定義的新註解添加功能。

三.一 @Target

表示可以定義的範圍, 具體看 枚舉 ElementType 的取值。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    
    ElementType[] value();
}

如 想使 @Table 只能放置在 類上面,不能放置在方法或者屬性上面。

@Target(ElementType.TYPE) //只能放置在類上
public @interface Table {


}

那麼,當將 @Table 放置在屬性,或者方法上時,就會出錯。

有圖片

@Id 和 @Column 定義在屬性上面。

@Target(ElementType.FIELD)
public @interface Id {

}
@Target(ElementType.FIELD)
public @interface Column {


}

當然, 範圍可以定義多個, 用數組傳遞即可。

@Target({ElementType.METHOD,ElementType.FIELD})
public @interface Name {
    
}

可以放置在 方法上面,也可以放置在屬性上面 。

三.二 @Retention

定義保存的範圍。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

用戶自定義的,建議使用 RUNTIME

@Target(ElementType.TYPE) //只能放置在類上
@Retention(RetentionPolicy.RUNTIME) //jvm虛擬機可以載入
public @interface Table {


}

三.三 @Documented

是否生成文檔

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

用戶自定義的,建議添加 @Documented, 默認不添加 。

三.四 @Inherited

是否繼承

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {

}

不建議添加繼承。

一般在自定義的註釋上面,添加 @Documented, @Target, @Retention 三個元註解即可。

四. 添加屬性

註解,裏面的是格式是: 數據類型 屬性值

屬性值,可以有一個,也可以有多個,也可以是數組形式, 可以添加默認值。

如果屬性只有一個的話, 均採用 value 屬性。 規定,如果一個註解只有一個屬性值,並且該屬性值爲 value 的話,那麼可以省略 value屬性。

如果屬性沒有默認值,那麼必須提供該屬性的值。

四.一 添加一個屬性值

@Target(ElementType.TYPE) //只能放置在類上
@Retention(RetentionPolicy.RUNTIME) //jvm虛擬機可以載入
@Documented
@Inherited
public @interface Table {

    //添加一個屬性值, 表名 
    String tableName();

}

應用到 Person 上面

@Table(tableName="person")
public class Person implements Serializable {

}

四.二 添加多個屬性值

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) //jvm虛擬機可以載入
@Documented
public @interface Column {

    //列名
    String name();
    //長度
    int length();

}

應用到 Person 上面

 @Column(name = "name",length = 50)
    private  String name;

四.三 添加默認值

用 default 默認值 即可。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) //jvm虛擬機可以載入
@Documented
public @interface Id {

    //默認列名是 id
    String name() default "id";

    //默認長度是 11 int 類型 
    int length() default 11;
}

應用到 Person 上面

@Id
 private int id;

四.四 添加數組類型

@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME) //jvm虛擬機可以載入
@Documented
public @interface Name {

    //填入值,數組形式
    String[] value() default {"兩個蝴蝶飛"};
    //注入
    String comment() default "一個快樂的程序員";
}

一個自定義的註解, 只有添加了作用範圍和 屬性值,纔算比較完整,纔可以使用。

一定要掌握創建註解的流程, 先創建基本的,再添加作用範圍,後添加屬性。


謝謝您的觀看,如果喜歡,請關注我,再次感謝 !!!

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