[轉]自定義註釋@interface的用法

1、什麼是註釋 
    提及註釋,得先提一提什麼是元數據(metadata)。所謂元數據就是數據的數據。也就是說,元數據是描述數據的。就象數據表中的字段同樣,每一個字段描述了這個字段下的數據的含義。而J2SE5.0中提供的註釋就是java源代碼的元數據,也就是說註釋是描述java源代碼的。在J2SE5.0中能夠自定義註釋。使用時在@後面跟註釋的名字。 
                                                   
2、J2SE5.0中預約義的註釋 
    在J2SE5.0的java.lang包中預約義了三個註釋。它們是Override、Deprecated和SuppressWarnings。下面分別解釋它們的含義。 
    1. Override註釋:僅用於方法(不可用於類、包或其餘),指明註釋的方法將覆蓋超類中的方法(若是覆蓋父類的方法而沒有注 
釋就沒法編譯該類),註釋還能確保註釋父類方法的拼寫是正確(錯誤的編寫,編譯器不認爲是子類的新方法,而會報錯) 
    2. @Deprecated註釋:對不該再使用的方法進行註釋,與正在聲明爲過期的方法放在同一行。使用被Deprecated註釋的方法,編譯器會 
提示方法過期警告(」Warring」) 
    3. @SuppressWarnings註釋:單一註釋,能夠經過數組提供變量,變量值指明要阻止的特定類型警告(忽略某些警告)。數組中的變量指明要阻止的警告@SuppressWarnings(value={」unchecked」, 」fallthrough」})) 

3、自定義註釋@interface 
@interface:註釋聲明,定義註釋類型(與默認的Override等三種註釋類型相似)。請看下面實例: java

註釋類1(類註釋): 數組

package a.test;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FirstAnno {
    String value() default "FirstAnno";
}

註釋類2(方法註釋): ide

package a.test;   
  
import java.lang.annotation.Documented;   
import java.lang.annotation.ElementType;   
import java.lang.annotation.Retention;   
import java.lang.annotation.RetentionPolicy;   
import java.lang.annotation.Target;   
  
@Documented   
@Retention(RetentionPolicy.RUNTIME)   
@Target(ElementType.METHOD)   
public @interface SecondAnnotation {   
    // 註釋中含有兩個參數   
    String name() default "Hrmzone";   
    String url() default "hrmzone.cn";   
}

註釋類3(成員變量註釋)函數

package a.test;   
  
import java.lang.annotation.Documented;   
import java.lang.annotation.ElementType;   
import java.lang.annotation.Retention;   
import java.lang.annotation.RetentionPolicy;   
import java.lang.annotation.Target;   
  
@Documented   
@Retention(RetentionPolicy.RUNTIME)   
@Target(ElementType.FIELD)   
public @interface Kitto {   
    String value() default "kitto";   
}

使用類: 測試

package a.test;

@FirstAnno("http://hrmzone.cn")   
public class Anno {   
@Kitto("測試")   
private String test = "";   
    // 不賦值註釋中的參數,使用默認參數   
    @SecondAnnotation()   
    public String getDefault() {   
            return "get default Annotation";   
    }   
    @SecondAnnotation(name="desktophrm",url="desktophrm.com")   
    public String getDefine() {   
            return "get define Annotation";   
    }
}

測試類: url

package a.test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class AnnoTest {
    public static void main(String[] args) throws ClassNotFoundException {
        // 要使用到反射中的相關內容
        Class c = Class.forName("a.test.Anno");
        Method[] method = c.getMethods();
        boolean flag = c.isAnnotationPresent(FirstAnno.class);
        if (flag) {
            FirstAnno first = (FirstAnno) c.getAnnotation(FirstAnno.class);
            System.out.println("First Annotation:" + first.value() + "\n");
        }

        List<Method> list = new ArrayList<Method>();
        for (int i = 0; i < method.length; i++) {
            list.add(method[i]);
        }

        for (Method m : list) {
            SecondAnnotation anno = m.getAnnotation(SecondAnnotation.class);
            if (anno == null)
                continue;

            System.out.println("second annotation's\nname:\t" + anno.name() + "\nurl:\t" + anno.url());
        }

        List<Field> fieldList = new ArrayList<Field>();
        for (Field f : c.getDeclaredFields()) {// 訪問全部字段
            Kitto k = f.getAnnotation(Kitto.class);
            System.out.println("----kitto anno: " + k.value());
        }
    }
}

    結合源文件中註釋,想必對註釋的應用有所瞭解。下面深刻了解。
    @Target:指定程序元定義的註釋所使用的地方,它使用了另外一個類:ElementType,是一個枚舉類定義了註釋類型能夠應用到不一樣的程序元素以避免使用者誤用。看看java.lang.annotation 下的源代碼: spa

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


    ElementType是一個枚舉類型,指明註釋能夠使用的地方,看看ElementType類: code

public enum ElementType {
    TYPE, // 指定適用點爲 class, interface, enum
    FIELD, // 指定適用點爲 field
    METHOD, // 指定適用點爲 method
    PARAMETER, // 指定適用點爲 method 的 parameter
    CONSTRUCTOR, // 指定適用點爲 constructor
    LOCAL_VARIABLE, // 指定使用點爲 局部變量
    ANNOTATION_TYPE, // 指定適用點爲 annotation 類型
    PACKAGE // 指定適用點爲 package
}

    @Retention:這個元註釋和java編譯器處理註釋的註釋類型方式相關,告訴編譯器在處理自定義註釋類型的幾種不一樣的選擇,須要使用RetentionPolicy枚舉類。此枚舉類只有一個成員變量,能夠不用指明成名名稱而賦值,看Retention的源代碼: blog

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

    類中有個RetentionPolicy類,也是一個枚舉類,具體看代碼: 繼承

public enum RetentionPolicy {
    SOURCE, // 編譯器處理完Annotation後不存儲在class中
    CLASS, // 編譯器把Annotation存儲在class中,這是默認值
    RUNTIME // 編譯器把Annotation存儲在class中,能夠由虛擬機讀取,反射須要
}

    @Documented:是一個標記註釋,表示註釋應該出如今類的javadoc中,由於在默認狀況下注釋時不包括在javadoc中的。 因此若是花費了大量的時間定義一個註釋類型,並想描述註釋類型的做用,能夠使用它。 
注意他與@Retention(RetentionPolicy.RUNTIME)配合使用,由於只有將註釋保留在編譯後的類文件中由虛擬機加載, 而後javadoc才能將其抽取出來添加至javadoc中。 
     @Inherited:將註釋一樣繼承至使用了該註釋類型的方法中(表達有點問題,就是若是一個方法使用了的註釋用了@inherited,那麼其子類的該方法一樣繼承了該註釋) 
注意事項:      1. 全部的Annotation自動繼承java.lang.annotation接口      2. 自定義註釋的成員變量訪問類型只能是public、default;(全部的都能訪問,源做者沒用到函數:getDeclaredFields而已)      3. 成員變量的只能使用基本類型(byte、short、int、char、long、double、float、boolean和String、Enum、Class、annotations以及該類型的數據)(沒有限制,你們能夠修改測試一下,就清楚)      4. 若是隻有一個成員變量,最好將參數名稱設爲value,賦值時不用制定名稱而直接賦值      5. 在實際應用中,還能夠使用註釋讀取和設置Bean中的變量。

相關文章
相關標籤/搜索