再談JAVA注解和反射

最近在研究阿里開源的ARouter框架冻记,碰到了較多注解的使用。結合ButterKnife開源框架的使用来惧,越來越體會到熟練使用注解的重要性冗栗。故針對注解再次進行學習和總結,重要的是輔助代碼來驗證。

Annotation注解

Annontation是Java5開始引入的新特征隅居,中文名稱叫注解钠至。它提供了一種安全的類似注釋的機制,用來將任何的信息或元數(shù)據(jù)(metadata)與程序元素(類胎源、方法棉钧、成員變量等)進行關聯(lián)。為程序的元素(類涕蚤、方法宪卿、成員變量)加上更直觀更明了的說明,這些說明信息是與程序的業(yè)務邏輯無關赞季,并且供指定的工具或框架使用愧捕。Annontation像一種修飾符一樣,應用于包申钩、類型、構造方法、方法、成員變量散罕、參數(shù)及本地變量的聲明語句中完箩。

Java注解是附加在代碼中的一些元信息,用于一些工具在編譯纠吴、運行時進行解析和使用,起到說明、配置的功能廉涕。注解不會也不能影響代碼的實際邏輯,僅僅起到輔助性的作用艇拍。包含在 java.lang.annotation 包中狐蜕。

JDK內(nèi)置注解

常用的標準注解有:

  1. @Override,主要用于在子類中覆蓋父類中的方法
  2. @Deprecated卸夕,用來標志被棄用的代碼层释,編譯器會進行警告
  3. @SuppressWarnings,用于忽略編譯器的警告信息快集。
    相信大家在日常工作中經(jīng)常使用以上三種注解贡羔。

元注解

開發(fā)人員可以根據(jù)自己的需要自定義注解,這時需要用到@Retention, @Target, @Inherited, @Documented這幾個元注解个初。

  1. @Rentention定義注解的保留級別乖寒。取值范圍是RetentionPolicy類型,源碼定義如下:
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

包括SOURCE:在代碼編寫階段存在院溺,編譯時被丟棄楣嘁。如@Override
CLASS:編譯階段注解保留在class文件中,VM運行時不需要保留。一般用來動態(tài)生成java代碼马澈,如ARouter瓢省,ButterKnife框架
RUNTIME:編譯階段注解保留在class文件中,VM運行時仍保留注解痊班。一般與反射結合使用勤婚,如Retrofit。

  1. @Target定義注解可以用于什么對象涤伐。取值范圍是ElementType類型馒胆,源碼定義如下:
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

其中常用的類型有TYPE:類、接口(包括注解)凝果、枚舉
FIELD:成員變量
METHOD:成員方法
PARAMETER:方法參數(shù)
ANNOTATION_TYPE:注解的注解

  1. @Documented標志注解將包含在Javadoc中

  2. @Inherited允許子類繼承父類中的注解

關于每種元注解的具體定義祝迂,可以在Android Studio中方便的查看源碼文件。reading the fuck code!

自定義注解

開發(fā)人員可以使用上面的元注解來定義自己的注解器净。示例如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimeAnno {
    String value();

    boolean isAlive() default false;
}

使用@interface定義注解型雳,類名即為注解名。自定義注解中只能定義方法山害,所有的方法均沒有參數(shù)纠俭,也沒有修飾符(默認是public&abstract修飾符),方法的返回值是基本類型浪慌、String冤荆、Classs、Annotation权纤、Enum或者對應的一位數(shù)組钓简。方法可以通過default設置默認值汹想。

注解使用時,如果只有一個方法欧宜,則可直接“注解名(值)”來使用坐榆;如果有多個方法冗茸,則需要依次賦值“注解名(方法名=值,方法名=值...)”夏漱。如果方法使用default賦值,則不必在使用時顯示賦值挂绰。

    @RuntimeAnno(value="11111")
    @RuntimeAnno("22222")
    @RuntimeAnno(value="33333", isAlive = true)

典型的注解定義如下圖:


Override注解定義
ButterKnife BindView注解定義
ButterKnife OnClick注解定義

其中服赎,ButterKnife的OnClick注解使用了自定義注解ListenerClass交播,具體定義可參考ButterKnife源碼。

運行時(RUNTIME)注解的解析

以Method為例秦士,參考Method的源碼缺厉,可以看到有如下幾個方法:

    /**
     * {@inheritDoc}
     * @throws NullPointerException  {@inheritDoc}
     * @since 1.5
     */
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        return super.getAnnotation(annotationClass);
    }

    /**
     * {@inheritDoc}
     * @since 1.5
     */
    public Annotation[] getDeclaredAnnotations()  {
        return super.getDeclaredAnnotations();
    }

    /**
     * {@inheritDoc}
     * @since 1.5
     */
    @Override
    public Annotation[][] getParameterAnnotations() {
        // Android-changed: This is handled by Executable.
        return super.getParameterAnnotationsInternal();
    }

其中getAnnotation(AnnotationName.class) 可獲取該 Target 某個 Annotation 的信息;因為一個 Target 可以被多個 Annotation 修飾.
getAnnotations() 則可獲取該 Target 所有 Annotation. getParameterAnnotations可以獲取方法的所有參數(shù)的注解隧土,返回值是一個二維數(shù)組提针。

其他Target,如Filed曹傀,Class辐脖,獲取Annotation的方法可參考java源碼。

高版本的jdk還有isAnnotationPresent(AnnotationName.class) 方法皆愉,來判斷Target 是否被某個 Annotation 修飾嗜价。

編譯時(CLASS)注解解析

編譯器解析編譯時注解,需要做的是1亥啦、自定義類繼承AbstractProcessor炭剪;2、重寫process函數(shù)翔脱。具體使用方法,可參考網(wǎng)上的其他文檔媒鼓。

ButterKnife就是使用編譯時注解届吁,生成JAVA文件。

注解的作用

1绿鸣、JDK標準注解疚沐,可用來生成JavaDoc,如@param @return潮模;可用來進行代碼檢查亮蛔,如@Override,@Deprecated擎厢。
2究流、目前較多框架使用注解,來自動生成代碼或替代配置文件的功能动遭。注解可以使編碼更簡潔芬探,學習注解可以理解使用開源框架,甚至自定義框架來解決問題厘惦。
3偷仿、注解和反射配合使用,可以使用簡潔的代碼實現(xiàn)復雜的功能,筆者目前的網(wǎng)絡庫入?yún)⒕筒捎昧俗⒔庠途玻瑒討B(tài)代理和反射技術节榜。可以參考反射注解與動態(tài)代理綜合使用别智,該文檔寫的簡單易懂宗苍。

參考文檔:
注解Annotation實現(xiàn)原理與自定義注解例子
反射注解與動態(tài)代理綜合使用
框架開發(fā)之Java注解的妙用

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市亿遂,隨后出現(xiàn)的幾起案子浓若,更是在濱河造成了極大的恐慌,老刑警劉巖蛇数,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挪钓,死亡現(xiàn)場離奇詭異碌上,居然都是意外死亡浦徊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門霞丧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蛹尝,“玉大人悉尾,你說我怎么就攤上這事°的眩” “怎么了惫霸?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵它褪,是天一觀的道長。 經(jīng)常有香客問我居触,道長,這世上最難降的妖魔是什么轮洋? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任弊予,我火速辦了婚禮,結果婚禮上误褪,老公的妹妹穿的比我還像新娘碾褂。我一直安慰自己,他們只是感情好嘀略,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布乓诽。 她就那樣靜靜地躺著,像睡著了一般讼育。 火紅的嫁衣襯著肌膚如雪稠集。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天,我揣著相機與錄音筷畦,去河邊找鬼刺洒。 笑死,一個胖子當著我的面吹牛鼎文,可吹牛的內(nèi)容都是我干的因俐。 我是一名探鬼主播周偎,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼蓉坎,長吁一口氣:“原來是場噩夢啊……” “哼蛉艾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衷敌,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤缴罗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后弓柱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侧但,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡禀横,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年柏锄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缭嫡。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡抬闷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出评架,到底是詐尸還是另有隱情炕泳,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布浙芙,位于F島的核電站,受9級特大地震影響茁裙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掉蔬,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一女轿、第九天 我趴在偏房一處隱蔽的房頂上張望壕翩。 院中可真熱鬧,春花似錦放妈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹭劈,卻和暖如春线召,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祟蚀。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留患雏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓丙挽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颜阐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,774評論 25 707
  • 前言 現(xiàn)在在我們構建自己或公司的項目中,或多或少都會依賴幾個流行比較屌的第三方庫肤舞,比如:Butter Knife、...
    戴定康閱讀 3,933評論 0 17
  • 時間的齒輪轉(zhuǎn)到了2018年,回首往昔萄窜,不知道你的感受是滿足呢撒桨?還是懊悔? 我想凤类,大多數(shù)人都是悔不當初的,奈何被歲月...
    諾feiyang閱讀 276評論 0 0
  • 互聯(lián)網(wǎng)賺錢的套路尺棋,就是用內(nèi)容把精準客戶引導到個人微信上,然后用催眠系統(tǒng)膘螟,加上激活系統(tǒng)來快速變現(xiàn)成交。 微信我們稱之...
    知聊閱讀 325評論 0 0
  • 兌為口奴艾,為說,不同的語言内斯,不同語氣給對方的不一樣的感覺,互相交流品擎,互相贊嘆,我們把向善的說出來萄传。 兌還有喜悅的意思...
    菜問媽媽閱讀 164評論 0 0