Java Annotation 總結

Annotation 被稱爲註解,在Java開發中是至關常見的,經過註解,咱們能夠簡化代碼提升開發效率。例如Override Annotation,這個應該算是在開發過程當中使用最多的註解了。下面這個例子是Android Activity的onCreate方法最經常使用的註解:數組

@Override
public void onCreate(Bundle savedInstanceState);
1.Annotation 概念

An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.app

譯文:ide

Annotation (註解) 表示的是可以添加到Java源代碼的語法元數據。類、方法、變量、參數、包均可以被註解,可用來將信息元數據和程序元素進行關聯。函數

2.Annotation 做用

a.標記做用,用於告訴編譯器一些信息ui

b.編譯時動態處理,如動態生成代碼spa

c.運行時動態處理,如獲得註解信息code

這三個做用對應着後面自定義Annotation時說的@Retention三種值分別表示的Annotationorm

3.Annotation 分類

a.標準 Annotation

包括 Override, Deprecated, SuppressWarnings,標準 Annotation 是指 Java 自帶的幾個 Annotation,上面三個分別表示重寫函數,不鼓勵使用(有更好方式、使用有風險或已不在維護),忽略某項 Warning對象

b.元 Annotation

@Retention, @Target, @Inherited, @Documented,元 Annotation 是指用來定義 Annotation 的 Annotation。blog

—@Documented:是否會保存到 Javadoc 文檔中

—@Retention:保留時間,可選值 SOURCE(源碼時),CLASS(編譯時),RUNTIME(運行時),默認爲 CLASS,值爲 SOURCE 大都爲 Mark Annotation,這類 Annotation 大都用來校驗,好比 Override, Deprecated, SuppressWarnings

—@Target:能夠用來修飾哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等,未標註則表示可修飾全部。

—@Inherited: 是否能夠被繼承,默認爲 false

c.自定義 Annotation

自定義 Annotation 表示自己根據須要定義的 Annotation,定義時須要用到上面的元 Annotation,這裏只是一種分類而已,也能夠根據做用域分爲源碼時、編譯時、運行時 Annotation。

4.Annotation 自定義

a.定義

下面實現了一個自定義註解—MethodInfo: 

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MethodInfo {
    String author() default "renhui";
    String date();
    int version() default 1;
}

 

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

b.調用

public class App {
    @MethodInfo(
        author = 「renhui」,
        date = "2016/01/14",
        version = 1)
    public String getAppName() {
        return "demo";
    }
}

 

這裏是調用自定義 Annotation——MethodInfo 的示例,MethodInfo Annotation 做用爲給方法添加相關信息,包括 author、date、version

c.解析

運行時 Annotation 解析

(1) 運行時 Annotation 指 @Retention 爲 RUNTIME 的 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 修飾
(2) 解析示例以下:

public static void main(String[] args) {
    try {
        Class cls = Class.forName("*.App");
        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 解析

(1) 編譯時 Annotation 指 @Retention 爲 CLASS 的 Annotation,甴 apt(Annotation Processing Tool) 解析自動解析。須要作的
a. 自定義類集成自 AbstractProcessor
b. 重寫其中的 process 函數
這塊不少同窗不理解,實際是 apt(Annotation Processing Tool) 在編譯時自動查找全部繼承自 AbstractProcessor 的類,而後調用他們的 process 方法去處理
(2) 假設以前自定義的 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 進行處理

使用編譯時註解很實用的例子:作代碼混淆時能夠經過添加編譯時註解並配合配置文件,達到指定的類、方法、對象等不進行混淆。

相關文章
相關標籤/搜索