目錄:
1.注解的編譯時處理
2.注解的運行時處理
上一篇學到注解的基本概念以及如何定義注解。
接下來學習如何提取注解(拿到注解的內容)並使用注解.
1.編譯時處理:
原理:APT技術
處理對象:@Retention=Source的注解
編譯時處理需要使用到APT技術,該技術提供了一套編譯期的注解處理流程。

在編譯期掃描.java文件的注解,並傳遞到注解處理器,注解處理器可根據注解生成新的.java文件,這些新的.java問和原來的.java一起被javac編譯。

這里需要引入注解處理器這個概念,注解處理器是一個在javac編譯期處理注解的工具,你可以創建注解處理器並注冊,在編譯期你創建的處理器以Java代碼作為輸入,生成文件.java文件作為輸出。
注意:注解處理器不能修改已經存在的Java類(即不能向已有的類中添加方法)。只能生成新的Java類。
2.運行時處理
原理: 通過反射機制獲取注解。
處理對象:@Retention=RUNTIME的注解
2.1判斷某個注解是否存在於Class、Field、Method或Constructor:
Class.isAnnotationPresent(Class)
Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
例如:判斷某個注解是否存在於Class
Class cls = Person.class;
if (cls.isAnnotationPresent(Report.class)) {
Report report = cls.getAnnotation(Report.class);
...
}
判斷某個注解是否存在於Field、Method或Constructor中與Class類似。
2.2直接從Class、Field、Method或Constructor讀取到Annotation:
Class.getAnnotation(Class)
Field.getAnnotation(Class)
Method.getAnnotation(Class)
Constructor.getAnnotation(Class)
例如直接從Class中讀取Annotation:
Class cls = Person.class;
Report report = cls.getAnnotation(Report.class);
if (report != null) {
...
}
直接從Field、Method或Constructor中與從Class中讀取類似。
2.3讀取方法參數的Annotation
比從Class、Field、Method或Constructor讀取麻煩一點。
因為方法參數本身可以看成一個數組,而每個參數又可以定義多個注解,所以,一次獲取方法參數的所有注解就必須用一個二維數組來表示。例如,對於以下方法定義的注解:
public void hello(@NotNull @Range(max=5) String name, @NotNull String prefix) {
}
要讀取方法參數的注解,我們先用反射獲取Method實例,然后讀取方法參數的所有注解:
// 獲取Method實例:
Method m = ...
// 獲取所有參數的Annotation:
Annotation[][] annos = m.getParameterAnnotations();
// 第一個參數(索引為0)的所有Annotation:
Annotation[] annosOfName = annos[0];
for (Annotation anno : annosOfName) {
if (anno instanceof Range) { // @Range注解
Range r = (Range) anno;
}
if (anno instanceof NotNull) { // @NotNull注解
NotNull n = (NotNull) anno;
}
}
讀取到注解后,就可以進行實際的業務代碼處理了。
運行時處理注解的缺點:
1:通過反射會影響運行效率
2:如果注解無法保存到運行時的話,是無法使用運行時處理的
