1. 程式人生 > >Annotation 深度剖析(一)

Annotation 深度剖析(一)

 一.  Annotation  介面(interface) 所有 annotation 型別 都要擴充套件的公共介面。 

 二. 列舉型別  

1. ElementType  程式元素型別  列舉類  通常是與 @target 元註釋型別一起使用,指定什麼情況使用註釋是合法的

public enum ElementType 

  extends Enum<ElementType>

    列舉常量

    (a). ANNOTATION_TYPE    //註釋型別宣告    

       (b).CONSTRUCTOR          //構造方法宣告

       (c).LOCAL_VARIABLE      //區域性變數宣告

     (d).PACKAGE                  //包宣告

     (e).PARAMETER            //引數型別宣告

     (d).TYPE                      //型別,介面(包括註釋型別)或者列舉宣告

2.RetentionPolicy   enum 列舉類 (儲存策略)

     (a).SOURCE    編譯器要丟棄的註釋 ,即儲存在原始碼期間,javadoc 後會被丟棄

     (b).CLASS     編譯器將把註釋記錄在類檔案中,但在執行時 VM 不需要保留註釋。這是預設的行為。

       (c). RUNTIME  編譯器將把註釋記錄在類檔案中,在執行時 VM 將保留註釋,因此可以反射性地讀取。

 三 註釋型別

     (a).Documented 指示某一型別的註釋將通過 javadoc 和類似的預設工具進行文件化。應使用此型別來註釋這些文件的宣告:其註釋會影響由其客戶端註釋的元素的使用。如果型別宣告是用Documented 來註釋的,則其註釋將成為註釋元素的公共API 的一部分。 (根據這段話的意識來理解,@Document  如果標記了@Document 來註解,如果匯出Api 文件的話,會把註解的 轉為 註解 的API) 原始碼如下:

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

    (b).Inherited  指示註釋型別會被自動繼承指示註釋型別被自動繼承。如果在註釋型別宣告中存在 Inherited 元註釋,並且使用者在某一類宣告中查詢該註釋型別,同時該類宣告中沒有此型別的註釋,則將在該類的超類中自動查詢該註釋型別。此過程會重複進行,直到找到此型別的註釋或到達了該類層次結構的頂層 (Object) 為止。如果沒有超類具有該型別的註釋,則查詢將指示當前類沒有這樣的註釋。(如果一個使用了@Inherited修飾的annotation型別被用於一個class,則這個annotation將被用於該class的子類。可以理解有穿透性)原始碼如下:

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

    (c).Retention    指示註釋型別的註釋要保留多久。如果註釋型別宣告中不存在 Retention 註釋,則保留策略預設為 RetentionPolicy.CLASS。只有元註釋型別直接用於註釋時,Target 元註釋才有效。如果元註釋型別用作另一種註釋型別的成員,則無效。(指註釋儲存時間,分為三種 :原始碼,執行中,編譯後)

四。註解  

      (a).AnnotationTypeMismatchException 若某個註釋的型別在對該註釋進行編譯(或序列化)後發生了更改,而程式試圖訪問該註釋的元素時,丟擲此異常。(執行時異常) 原始碼如下:

 

public class AnnotationTypeMismatchException extends RuntimeException {
    private static final long serialVersionUID = 8125925355765570191L;

    /**
     * The <tt>Method</tt> object for the annotation element.
     */
    private final Method element;

    /**
     * The (erroneous) type of data found in the annotation.  This string
     * may, but is not required to, contain the value as well.  The exact
     * format of the string is unspecified.
     */
    private final String foundType;

    /**
     * Constructs an AnnotationTypeMismatchException for the specified
     * annotation type element and found data type.
     *
     * @param element the <tt>Method</tt> object for the annotation element
     * @param foundType the (erroneous) type of data found in the annotation.
     *        This string may, but is not required to, contain the value
     *        as well.  The exact format of the string is unspecified.
     */
    public AnnotationTypeMismatchException(Method element, String foundType) {
        super("Incorrectly typed data found for annotation element " + element
              + " (Found data of type " + foundType + ")");
        this.element = element;
        this.foundType = foundType;
    }

    /**
     * Returns the <tt>Method</tt> object for the incorrectly typed element.
     *
     * @return the <tt>Method</tt> object for the incorrectly typed element
     */
    public Method element() {
        return this.element;
    }

    /**
     * Returns the type of data found in the incorrectly typed element.
     * The returned string may, but is not required to, contain the value
     * as well.  The exact format of the string is unspecified.
     *
     * @return the type of data found in the incorrectly typed element
     */
    public String foundType() {
        return this.foundType;
    }
}

    (b).IncompleteAnnotationException  若某個註釋在編譯(或序列化)後將某個註釋型別新增到其型別定義中,而程式試圖該註釋型別的元素時,丟擲此異常。如果新元素有預設值,則不丟擲此異常。原始碼如下

public class IncompleteAnnotationException extends RuntimeException {
    private static final long serialVersionUID = 8445097402741811912L;

    private Class<? extends Annotation> annotationType;
    private String elementName;

    /**
     * Constructs an IncompleteAnnotationException to indicate that
     * the named element was missing from the specified annotation type.
     *
     * @param annotationType the Class object for the annotation type
     * @param elementName the name of the missing element
     * @throws NullPointerException if either parameter is {@code null}
     */
    public IncompleteAnnotationException(
            Class<? extends Annotation> annotationType,
            String elementName) {
        super(annotationType.getName() + " missing element " +
              elementName.toString());

        this.annotationType = annotationType;
        this.elementName = elementName;
    }

    /**
     * Returns the Class object for the annotation type with the
     * missing element.
     *
     * @return the Class object for the annotation type with the
     *     missing element
     */
    public Class<? extends Annotation> annotationType() {
        return annotationType;
    }

    /**
     * Returns the name of the missing element.
     *
     * @return the name of the missing element
     */
    public String elementName() {
        return elementName;
    }
}

(c).AnnotationFormatError  錯誤 

       構造一個指示指定註釋型別中缺少指定元素的 IncompleteAnnotationException。

       引數:

  annotationType - 註釋型別的 Class 物件

  elementName - 缺少元素的名稱