1.? Java SE5中內(nèi)置了3中標準注解,以及4中元注解(用于注解其他的注解),注解一旦構(gòu)造出來就享有編譯期的類型檢查保護。
注解元素可用的類型
String
Class
enum
Annotation
以上類型的數(shù)組
3種標準注解:@Override,@Deprecated,@SuppressWarnings
4種元注解:
注解分類按生命周期由短到長可分為:
RetentionPolicy.SOURCE:源碼注解,注解只保留在源文件,當Java文件編譯成class文件的時候,注解被遺棄(在編譯器處理期間源碼注解還存在,即注解處理器Processor也能處理源碼注解,編譯器處理完之后就沒有該注解信息了);
RetentionPolicy.CLASS:編譯時注解,注解被保留到class文件,但jvm加載class文件時候被遺棄,這是默認的生命周期;
RetentionPolicy.RUNTIME:運行時注解,注解不僅被保存到class文件中,jvm加載class文件之后,仍然存在;
這3個生命周期分別對應(yīng)于:Java源文件(.java文件) ---> .class文件?--->?內(nèi)存中的字節(jié)碼。
首先要明確生命周期長度SOURCE < CLASS < RUNTIME,所以前者能作用的地方后者一定也能作用。一般如果需要在運行時去動態(tài)獲取注解信息,那只能用?RUNTIME 注解;如果要在編譯時進行一些預處理操作,比如生成一些輔助代碼(如ButterKnife),就用?CLASS注解;如果只是做一些檢查性的操作,比如@Override和@SuppressWarnings,則可選用?SOURCE 注解。
獲取注解的方式:
需要通過反射來獲取運行時注解,要使用這些函數(shù)必須先通過反射獲取到對應(yīng)的元素:Class、Field、Method,再通過getDeclaredAnnotations()拿到注解。
編譯時注解需要用注解處理器(Annotation Processor)來獲取,因為這里是真正體現(xiàn)編譯時注解價值的地方。需要注意的一點是,運行時注解(RetentionPolicy.RUNTIME)和源碼注解(RetentionPolicy.SOURCE)也可以在注解處理器進行處理
2.在Android Support Library19.1版本中,Android工具小組引入了幾個注解類型
有三種類型的注解可供我們使用:
@Retention(SOURCE)都是源碼注解
Nullness注解;
資源類型注解;
IntDef和StringDef注解;
3.注解處理器
主要用于處理編譯時注解,注解處理器只在編譯處理期間需要用到,編譯處理完后就沒有實際作用了。
注解處理器是javac的一個工具,它用來在編譯時掃描和處理注解(Annotation)。你可以自定義注解,并注冊到相應(yīng)的注解處理器,由注解處理器來處理你的注解。注解處理器,以Java代碼(或者編譯過的字節(jié)碼)作為輸入,生成文件(通常是.java文件)作為輸出。
每一個處理器都是繼承于AbstractProcessor,并要求必須復寫process()方法,通常我們使用會去復寫以下4個方法:
init(ProcessingEnvironment env): 每一個注解處理器類都必須有一個空的構(gòu)造函數(shù)。然而,這里有一個特殊的init()方法,它會被注解處理工具調(diào)用,并輸入ProcessingEnviroment參數(shù)。ProcessingEnviroment提供很多有用的工具類Elements, Types和Filer。后面我們將看到詳細的內(nèi)容。
process(Set annotations, RoundEnvironment env): 這相當于每個處理器的主函數(shù)main()。你在這里寫你的掃描、評估和處理注解的代碼,以及生成Java文件。輸入?yún)?shù)RoundEnviroment,可以讓你查詢出包含特定注解的被注解元素。后面我們將看到詳細的內(nèi)容。
getSupportedAnnotationTypes(): 這里你必須指定,這個注解處理器是注冊給哪個注解的。注意,它的返回值是一個字符串的集合,包含本處理器想要處理的注解類型的合法全稱。換句話說,你在這里定義你的注解處理器注冊到哪些注解上。
getSupportedSourceVersion(): 用來指定你使用的Java版本。通常這里返回SourceVersion.latestSupported()。然而,如果你有足夠的理由只支持Java 6的話,你也可以返回SourceVersion.RELEASE_6。我推薦你使用前者。