為什么要學注解
- 要想看懂很多開源庫,如Arouter, dagger,Butter Knife等,不得不先看懂注解;
- 想更好地提升開發效率和代碼質量,注解可以幫上很大的忙;
本文主要介紹注解開發的大概概念,算是入個門,如果想實踐,請關注后續文章
一、什么是注解
JAVA.lang.annotation,接口 Annotation,在JDK5.0及以后版本引入。
注解是代碼里的特殊標記,這些標記可以在編譯、類加載、運行時被讀取,并執行相應的處理。通過使用Annotation,開發人員可以在不改變原有邏輯的情況下,在源文件中嵌入一些補充的信息。代碼分析工具、開發工具和部署工具可以通過這些補充信息進行驗證、處理或者進行部署。
在運行時讀取需要使用Java反射機制進行處理。
Annotation不能運行,它只有成員變量,沒有方法。Annotation跟public、final等修飾符的地位一樣,都是程序元素的一部分,Annotation不能作為一個程序元素使用。
其實大家都是用過注解的,只是可能沒有過深入了解它的原理和作用,比如肯定見過@Override,@Deprecated等。
1、注解的作用
注解將一些本來重復性的工作,變成程序自動完成,簡化和自動化該過程。比如用于生成Java doc,比如編譯時進行格式檢查,比如自動生成代碼等,用于提升軟件的質量和提高軟件的生產效率。
2、注解都有哪些
平時我們使用的注解有來自JDK里包含的,也有Android SDK里包含的,也可以自定義。
2.1、JDK定義的元注解
Java提供了四種元注解,專門負責新注解的創建工作,即注解其他注解。
@target 定義了Annotation所修飾的對象范圍
ElementType.CONSTRUCTOR:用于描述構造器
ElementType.FIELD:用于描述域
ElementType.LOCAL_VARIABLE:用于描述局部變量
ElementType.METHOD:用于描述方法
ElementType.PACKAGE:用于描述包
ElementType.PARAMETER:用于描述參數
ElementType.TYPE:用于描述類、接口(包括注解類型) 或enum聲明
@retention 定義了該Annotation被保留的時間長短,取值
- RetentionPoicy.SOURCE:注解只保留在源文件,當Java文件編譯成class文件的時候,注解被遺棄;用于做一些檢查性的操作,比如 @Override 和 @SuppressWarnings
- RetentionPoicy.CLASS:注解被保留到class文件,但jvm加載class文件時候被遺棄,這是默認的生命周期;用于在編譯時進行一些預處理操作,比如生成一些輔助代碼(如 ButterKnife)
- RetentionPoicy.RUNTIME:注解不僅被保存到class文件中,jvm加載class文件之后,仍然存在;用于在運行時去動態獲取注解信息。
@documented 標記注解,用于描述其它類型的注解應該被作為被標注的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化,不用賦值。
@inherited 標記注解,允許子類繼承父類的注解。 這里一開始有點理解不了,需要斷句一下,允許子類繼承父類的注解。示例:
Target(value = ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Sample { public String name() default ""; } @Sample class Test{ } class Test2 extents Test{ }
這樣類Test2其實也有注解@sample 。
2.2 JDK內置的其他注解
Android 開發中經常使用各種資源常量 R.XXX 來引用各種資源。例如 圖片資源和字符串資源。這些常量都是 int 類型的,在代碼檢測的時候沒法判斷引用的資源是否有錯誤,比如本來需要一個字符串資源,結果在代碼寫的時候用了一個顏色資源,這種情況只有通過測試才能發現,有些極端情況可能測試也不容易發現。資源類型注解就是為了解決該問題的,資源注解包含如下幾種:
資源類型注解
@AnimatorRes 表明該參數、變量或者函數返回值應該是一個 Animator 類型的資源
@AnimRes 表明該參數、變量或者函數返回值應該是一個 Anim 類型的資源
@AnyRes 表明該參數、變量或者函數返回值應該是一個任意類型的資源
@ArrayRes 表明該參數、變量或者函數返回值應該是一個 Array 類型的資源
@AttrRes 表明該參數、變量或者函數返回值應該是一個 attribute 類型的資源
@BoolRes 表明該參數、變量或者函數返回值應該是一個布爾類型的資源
@ColorInt 表明該參數、變量或者函數返回值應該是一個顏色值而不是顏色資源引用,例如應該是一個 AARRGGBB 的整數值。
@ColorRes 表明該參數、變量或者函數返回值應該是一個 color 類型的資源,而不是顏色值。注意和 ColorInt 區別
@DimenRes 表明該參數、變量或者函數返回值應該是一個 dimension 類型的資源
@DrawableRes 表明該參數、變量或者函數返回值應該是一個 drawable 類型的資源
@FractionRes 表明該參數、變量或者函數返回值應該是一個 fraction 類型的資源
@IdRes 表明該參數、變量或者函數返回值應該是一個資源的 ID 類型
@IntegerRes 表明該參數、變量或者函數返回值應該是一個整數類型的資源
@LayoutRes 表明該參數、變量或者函數返回值應該是一個 layout 布局文件類型的資源
@MenuRes 表明該參數、變量或者函數返回值應該是一個 menu 類型的資源
@PluralsRes 表明該參數、變量或者函數返回值應該是一個 plurals 類型的資源
@RawRes 表明該參數、變量或者函數返回值應該是一個 raw 類型的資源
@StringRes 表明該參數、變量或者函數返回值應該是一個字符串類型的資源
@StyleableRes 表明該參數、變量或者函數返回值應該是一個 styleable 類型的資源
@StyleRes 表明該參數、變量或者函數返回值應該是一個 style 類型的資源
@TransitionRes 表明該參數、變量或者函數返回值應該是一個 transition 類型的資源
@XmlRes 表明該參數、變量或者函數返回值應該是一個 XML 類型的資源
線程注解類型
線程注解用來檢測一個函數是否在指定類型的線程中執行。 有四個:
- @UiThread
- @MainThread
- @WorkerThread
- @BinderThread
注意: 其中 @UiThread 和 @MainThread 是可替換用的, 大部分應用中,這兩個是一樣的。
如果一個類中的所有函數都在同一個線程內執行,可以在 類名稱上面用這個注解即可。
權限注解類型
@RequiresPermission 用來表明該函數執行需要一個或者多個權限,如果你沒有聲明這些權限,則會給出警告。例如:
@RequiresPermission(Manifest.permission.SET_WALLPAPER) public abstract void setWallpaper(Bitmap bitmap) throws IOException; @RequiresPermission(allOf = { Manifest.permission.READ_HISTORY_BOOKMARKS, Manifest.permission.WRITE_HISTORY_BOOKMARKS}) public static final void updateVisitedHistory(ContentResolver cr, String url, boolean real) { } @RequiresPermission(anyOf = { Manifest.permission.READ_HISTORY_BOOKMARKS, Manifest.permission.WRITE_HISTORY_BOOKMARKS}) public static final void updateHistory(ContentResolver cr, String url, boolean real) { }
結束
漫漫開發之路,我們只是其中的一小部分……只有不斷的學習、進階,才是我們的出路!才跟得上時代的進步!
今年年初我花一個月的時間收錄整理了一套知識體系,如果有想法深入的系統化的去學習的,可以私信我【安卓】,我會把我收錄整理的資料都送給大家,幫助大家更快的進階。