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