Android中的註解入門篇——Java註解

1. 註解的分類

  • 標準註解
    包括以下幾種註解成爲標準註解,這三種是在JDK5之後包含的標準註解(annotation)。
    Overide——表示該函數被覆蓋重寫
    Deprecated——表示該函數或者類被廢棄,已經不再維護
    SuppressWarnings——表示告訴Java編譯器關閉對這些方法、類、成員的警告

  • 元註解
    元註解表示用來自定義其他註解的註解,有以下四種。

    註解 用法示例 說明
    @Target @Target(ElementType.METHOD) 表示該註解可以用於什麼地方,可能的ElementType參數有:
    CONSTRUCTOR:構造器的聲明
    FIELD:域聲明(包括enum實例)
    LOCAL_VARIABLE:局部變量聲明
    METHOD:方法聲明
    PACKAGE:包聲明
    PARAMETER:參數聲明
    TYPE:類、接口(包括註解類型)或enum聲明
    @Retention @Retention(RetentionPolicy.RUNTIME) 表示需要在什麼級別保存該註解信息。可選的RetentionPolicy參數包括:
    SOURCE:註解將被編譯器丟棄
    CLASS:註解在class文件中可用,但會被VM丟棄
    RUNTIME:VM將在運行期間保留註解,因此可以通過反射機制讀取註解的信息。
    @Documented @Documented 將註解包含在Javadoc中
    @Inherited @Inherited 允許子類繼承父類中的註解

  • 在元註解基礎上自定義的註解

2.自定義註解

沒有元素的註解叫做標記註解(mark annotation),下面就是一個標記註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MarkAnnotation {

}

下面的MethodInfo是一個比較完整的註解

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

    String author() default "[email protected]";

    String date();

    int version() default 1;
}

在MethodInfo的實現上有以下幾點

  • 通過 @interface 定義,註解名即爲自定義註解名
  • 註解配置參數名爲註解類的方法名,且:
    a. 所有方法沒有方法體,沒有參數沒有修飾符,實際只允許 public & abstract 修飾符,默認爲 public ,不允許拋異常
    b. 方法返回值只能是基本類型,String, Class, annotation, enumeration 或者是他們的一維數組
    c. 若只有一個默認屬性,可直接用 value() 函數。一個屬性都沒有表示該 Annotation 爲 Mark Annotation
  • 可以加 default 表示默認值

  • 註解的可用的類型包括以下幾種:所有基本類型、String、Class、enum、Annotation、以上類型的數組形式。元素不能有不確定的值,即要麼有默認值,要麼在使用註解的時候提供元素的值。而且元素不能使用null作爲默認值。註解在只有一個元素且該元素的名稱是value的情況下,在使用註解的時候可以省略“value=”,直接寫需要的值即可。

3.註解的使用

還是以上面的MethodInfo爲例,該註解是一個方法註解。

public Example{
    @MethodInfo(author="gaoyan", date="2015-05-30", version=2)
    public boolean isGoodExample() {
        return true;
    }
    @MethodInfo(date="2015-05-30")
    public boolean isBadExample() {
        return false;
    }
}

4.註解的解析

  • 運行時的Annotation解析
    對於@Retention(RetentionPolicy=RUNTIME)、@Target(ElementType.METHOD)的Annotation,可以使用下面的API解析:
method.getAnnotation(AnnotationName.class);
method.getAnnotations();
method.isAnnotationPresent(AnnotationName.class);

其他 @Target 如 Field,Class 方法類似

  • getAnnotation(AnnotationName.class) 表示得到該 Target 某個 Annotation 的信息,因爲一個 Target 可以被多個 Annotation 修飾
  • getAnnotations() 則表示得到該 Target 所有 Annotation
  • isAnnotationPresent(AnnotationName.class) 表示該 Target 是否被某個 Annotation 修飾
public static void main(String[] args) {
    try {
        Class cls = Class.forName("Example");
        for (Method method : cls.getMethods()) {
            MethodInfo methodInfo = method.getAnnotation(
MethodInfo.class);
            if (methodInfo != null) {
                System.out.println("method name:" + method.getName());
                System.out.println("method author:" + methodInfo.author());
                System.out.println("method version:" + methodInfo.version());
                System.out.println("method date:" + methodInfo.date());
            }
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}
  • 編譯時的Annotation解析
    編譯時 Annotation 指 @Retention 爲 CLASS 的 Annotation,甴編譯器自動解析。需要做的

    • 自定義類集成自 AbstractProcessor
    • 重寫其中的 process 函數

    假設 MethodInfo 的 @Retention 爲 CLASS,解析示例如下:

@SupportedAnnotationTypes({ "MethodInfo" })
public class MethodInfoProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
        HashMap<String, String> map = new HashMap<String, String>();
        for (TypeElement te : annotations) {
            for (Element element : env.getElementsAnnotatedWith(te)) {
                MethodInfo methodInfo = element.getAnnotation(MethodInfo.class);
                map.put(element.getEnclosingElement().toString(), methodInfo.author());
            }
        }
        return false;
    }
}

SupportedAnnotationTypes 表示這個 Processor 要處理的 Annotation 名字。
process 函數中參數 annotations 表示待處理的 Annotations,參數 env 表示當前或是之前的運行環境
process 函數返回值表示這組 annotations 是否被這個 Processor 接受,如果接受後續子的 rocessor 不會再對這個 Annotations 進行處理

  1. 參考https://github.com/android-cn/android-open-project-analysis/blob/master/tech/annotation.md
  2. 參考 http://www.cnblogs.com/pepcod/archive/2013/02/16/2913474.html
發佈了32 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章