前言
對於註解,相信大家都不陌生了,但是這種熟悉對於Android開發者來說,也就是僅僅是它認識你,你不認識它吧,因為,我們幾乎都停留在用上了。像dagger2,像retrofit,像greenDao,他們都是滿滿的使用了註解,而我們只是停留在知其然缺不知其所以然的層面,那麼我本次分享講分成幾批部落格共享給大家一個體系的又不失針對Android平臺需要的恰到好處的給大家整理真正需要掌握的知識體系。
註解
註解的定義
Java 註解用於為 Java 程式碼提供後設資料。作為後設資料,註解不直接影響你的程式碼執行,但也有一些型別的註解實際上可以用於這一目的。Java 註解是從 Java5 開始新增到 Java 的。
註解即標籤
如果把程式碼想象成一個具有生命的個體,註解就是給這些程式碼的某些個體打標籤
如何自定義註解
- 註解通過 @interface關鍵字進行定義。
public @interface Test {
}複製程式碼
它的形式跟介面很類似,不過前面多了一個 @ 符號。上面的程式碼就建立了一個名字為 Test 的註解。
你可以簡單理解為建立了一張名字為 Test的標籤。
- 使用註解
@Test
public class TestAnnotation {
}複製程式碼
建立一個類 TestAnnotation,然後在類定義的地方加上 @Test就可以用 Test註解這個類了
你可以簡單理解為將 Test 這張標籤貼到 TestAnnotation這個類上面。
元註解
元註解是可以註解到註解上的註解,或者說元註解是一種基本註解,但是它能夠應用到其它的註解上面。
如果難於理解的話,你可以這樣理解。元註解也是一張標籤,但是它是一張特殊的標籤,它的作用和目的就是給其他普通的標籤進行解釋說明的。
元標籤有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 種。
- @Retention
- Retention 的英文意為保留期的意思。當 @Retention 應用到一個註解上的時候,它解釋說明了這個註解的的存活時間。
- 它的取值如下:
- RetentionPolicy.SOURCE 註解只在原始碼階段保留,在編譯器進行編譯時它將被丟棄忽視。
- RetentionPolicy.CLASS 註解只被保留到編譯進行的時候,它並不會被載入到 JVM 中。
- RetentionPolicy.RUNTIME 註解可以保留到程式執行的時候,它會被載入進入到 JVM 中,所以在程式執行時可以獲取到它們
- @Target
- Target 是目標的意思,@Target 指定了註解運用的地方
- 你可以這樣理解,當一個註解被 @Target 註解時,這個註解就被限定了運用的場景。
- 類比到標籤,原本標籤是你想張貼到哪個地方就到哪個地方,但是因為 @Target 的存在,它張貼的地方就非常具體了,比如只能張貼到方法上、類上、方法引數上等等。@Target 有下面的取值
- ElementType.ANNOTATION_TYPE 可以給一個註解進行註解
- ElementType.CONSTRUCTOR 可以給構造方法進行註解
- ElementType.FIELD 可以給屬性進行註解
- ElementType.LOCAL_VARIABLE 可以給區域性變數進行註解
- ElementType.METHOD 可以給方法進行註解
- ElementType.PACKAGE 可以給一個包進行註解
- ElementType.PARAMETER 可以給一個方法內的引數進行註解
- @Documented
- 顧名思義,這個元註解肯定是和文件有關。它的作用是能夠將註解中的元素包含到 Javadoc 中去。ElementType.TYPE 可以給一個型別進行註解,比如類、介面、列舉
- @Inherited
- Inherited 是繼承的意思,但是它並不是說註解本身可以繼承,而是說如果一個超類被 @Inherited 註解過的註解進行註解的話,那麼如果它的子類沒有被任何註解應用的話,那麼這個子類就繼承了超類的註解。
- @Repeatable
- Repeatable 自然是可重複的意思。@Repeatable 是 Java 1.8 才加進來的,所以算是一個新的特性。
- 什麼樣的註解會多次應用呢?通常是註解的值可以同時取多個。
註解的屬性
註解的屬性也叫做成員變數。註解只有成員變數,沒有方法。
需要注意的是,在註解中定義屬性時它的型別必須是 8 種基本資料型別外加 類、介面、註解及它們的陣列
註解中屬性可以有預設值,預設值需要用 default 關鍵值指定
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
int id() default -1;
String msg() default "Hello";
}複製程式碼
上面程式碼定義了 TestAnnotation 這個註解中擁有 id 和 msg 兩個屬性。在使用的時候,我們應該給它們進行賦值。
賦值的方式是在註解的括號內以 value="" 形式,多個屬性之前用 ,隔開
@Test(id=1,msg="hello annotation")
public class TestAnnotation {
}複製程式碼
註解的提取
註解與反射。
註解通過反射獲取。首先可以通過 Class 物件的 isAnnotationPresent() 方法判斷它是否應用了某個註解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}複製程式碼
然後通過 getAnnotation() 方法來獲取 Annotation 物件。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {複製程式碼
或者是 getAnnotations() 方法。
public Annotation[] getAnnotations() {}複製程式碼
前一種方法返回指定型別的註解,後一種方法返回註解到這個元素上的所有註解。
如果獲取到的 Annotation 如果不為 null,則就可以呼叫它們的屬性方法了。比如
@Test()
public class TestDemo{
public static void main(String[] args) {
boolean hasAnnotation = TestDemo.class.isAnnotationPresent(Test.class);
if ( hasAnnotation ) {
TestAnnotation testAnnotation = TestDemo.class.getAnnotation(Test.class);
System.out.println("id:"+testAnnotation.id());
System.out.println("msg:"+testAnnotation.msg());
}
}
}複製程式碼
註解的使用場景
- 提供資訊給編譯器: 編譯器可以利用註解來探測錯誤和警告資訊
- 編譯階段時的處理: 軟體工具可以用來利用註解資訊來生成程式碼、Html文件或者做其它相應處理。
- 執行時的處理: 某些註解可以在程式執行的時候接受程式碼的提取
- 值得注意的是,註解不是程式碼本身的一部分。
最後
讀到這的朋友覺得不錯可以點贊關注下,感謝您的支援,以後會不停更新更多精選乾貨及資訊分享,歡迎大家在評論區留言討論!
歡迎關注享學課堂online微信公眾號,每天會持續更新技術乾貨,熱點,吐槽等文章,還有免費的Android架構視訊資料和麵試專題資料免費領取分享,後臺回覆關鍵字【Android資料】,免費獲取Android架構面試專題文件資料、電子書及更多架構進階視訊資料(視訊+筆記)