Kotlin-34.注解(Annotation)

官方文檔: http://kotlinlang.org/docs/reference/annotations.html

1.聲明注解(Annotation Declaration)

和java類似,kotlin注解就是在代碼中附加元數(shù)據(jù)(metadata),
聲明注解(在class前面添加annotation修飾符):
    annotation class Fancy

和java注解類似,kotlin注解的附加屬性可以通過元注解(meta-annotation)來聲明指定,
kotlin元注解(meta-annotation)有以下幾種:
    @Target 注解目標(biāo): 指定該注解用于什么類型的元素(類,函數(shù),屬性,表達式等);
    @Retention 注解保留: 指定該注解是否存在編譯后的class文件,以及在運行時能否通過反射可見(默認都是true);
    @Repeatable 允許該注解在單個元素上多次使用;        
    @MustBeDocumented 指定該注解是公有API的一部分,且應(yīng)該包含在生成的API文檔中(類或方法的文檔注釋)

注解聲明(包括元注解)的示例:
    @Target(AnnotationTarget.CLASS, //用于類
            AnnotationTarget.FUNCTION, //用于函數(shù)
            AnnotationTarget.VALUE_PARAMETER, //用于函數(shù)參數(shù)
            AnnotationTarget.EXPRESSION) //用于表達式
    @Retention(AnnotationRetention.SOURCE) //表示注解只存在源碼,不在編譯后的class文件
    @MustBeDocumented //包含在API文檔中
    annotation class Fancy

2.使用注解(Usage)

@Fancy class Foo {
    @Fancy fun baz(@Fancy foo: Int): Int {
        return (@Fancy 1)
    }
}

1.對類的主構(gòu)造函數(shù)進行注解,需要在構(gòu)造函數(shù)前面添加constructor關(guān)鍵字,注解添加到它的前面:
    class Foo @Inject constructor(dependency: MyDependency) {
        //...
    }
    
2.對屬性訪問器(get/set)進行注解:
    class Foo {
        var x: MyDependency? = null
            @Inject set
    }

3.對Lambda表達式進行注解:    
    annotation class Suspendable

    val f = @Suspendable { Fiber.sleep(10) }

3.聲明注解的構(gòu)造函數(shù)(Constructors)

注解可以有構(gòu)造函數(shù)(用于接受參數(shù)):
    //聲明注解
    @Target(AnnotationTarget.CLASS)        
    annotation class Special(val why: String)

    //使用注解
    @Special("example") class Foo {}

1.kotlin注解的參數(shù)類型:
    和Java原生類型對應(yīng)的kotlin類型(Int,Long等);
    字符串string;
    kotlin類class(Foo::class);
    枚舉enum;
    其它注解;
    以上類型構(gòu)成的數(shù)組; 

    提示: 注解參數(shù)不能有可空(null)類型,因為JVM不支持存儲null作為注解屬性值!

2.注解作為另一個注解的參數(shù),不需要添加@前綴:
    annotation class ReplaceWith(val expression: String)

    //ReplaceWith作為注解參數(shù)時,不需要加@前綴
    annotation class Deprecated(
            val message: String,
            val replaceWith: ReplaceWith = ReplaceWith(""))

    @Deprecated("This function is deprecated, use === instead", 
        ReplaceWith("this === other"))

3.kotlin類作為注解的參數(shù)
如果需要將一個類指定為注解的參數(shù),請用Kotlin類(KClass),
Kotlin編譯器會自動將Kotlin類轉(zhuǎn)換為Java類,以便Java代碼能正常使用該注解和參數(shù)!
    import kotlin.reflect.KClass
    annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any?>)

    @Ann(String::class, Int::class) class MyClass

4.精確注解/使用處目標(biāo)(Annotation Use-site Targets)

當(dāng)對屬性或主構(gòu)造函數(shù)參數(shù)進行注解時,一個Kotlin屬性元素會生成多個Java元素,
說白了就是,主構(gòu)造函數(shù)參數(shù)(有val/var)就是kotlin類屬性,
而[kotlin類屬性]就相當(dāng)于[Java類field字段+get方法+set方法],
因此在kotlin源碼編譯成Java字節(jié)碼時,該注解可能同時在多個元素上!

1.對屬性元素(set/get/field/param)進行精確注解:
    //Ann是注解,@xx:是固定語法
    class Example(@field:Ann val foo, //對Java 字段 進行注解
                @get:Ann val bar,     //對Java get方法 進行注解
                @param:Ann val quux)  //對Java 構(gòu)造函數(shù)參數(shù) 進行注解

2.同一目標(biāo)元素有多個注解,可在方括號[]添加多個注解,空格分隔:
    class Example {
        //collaborator的set方法有兩個注解Inject和VisibleForTesting
        @set:[Inject VisibleForTesting] 
        var collaborator: Collaborator
    }

3.使用相同語法注解整個文件,把@file注解放在文件的頂層(package指令之前):
    @file:JvmName("Foo")
    package org.jetbrains.demo

4.使用處目標(biāo)(use-site target)的完整列表:
    @file:
    @property: (具有此目標(biāo)的注解對Java不可見)
    @field:
    @get:      (屬性的getter方法)
    @set:      (屬性的setter方法)
    @receiver: (擴展函數(shù)或?qū)傩缘慕邮照邊?shù))
    @param:    (構(gòu)造函數(shù)參數(shù))
    @setparam: (屬性的setter方法參數(shù))
    @delegate: (為委托屬性存儲其委托實例對象的字段)

    對擴展函數(shù)的接收者參數(shù)進行注解,語法如下:
        fun @receiver:Fancy String.myExtension() { }

    如果不指定使用處目標(biāo),則根據(jù)注解的@Target來選擇目標(biāo),有多個適用目標(biāo),
    則用以下列表的第一個目標(biāo):
        param
        property
        field

5.在Kotlin中使用Java注解(Java Annotation)

Java注解 與Kotlin 100%兼容,示例如下:
    // 導(dǎo)入Java注解
    import org.junit.Test
    import org.junit.Assert.*
    import org.junit.Rule
    import org.junit.rules.*

    // kotlin代碼,使用java注解
    class Tests {
        // @Rule注解用于tempFolder屬性的getter方法/函數(shù)
        @get:Rule val tempFolder = TemporaryFolder()

        // @Test注解用于simple方法/函數(shù)
        @Test fun simple() {
            val f = tempFolder.newFile()
            assertEquals(42, getTheAnswer())
        }
    }

1.因為Java聲明的注解沒有定義參數(shù)順序,所以kotlin需要使用命名參數(shù)來傳遞注解參數(shù):
    // Java代碼,聲明注解Ann
    public @interface Ann {
        int intValue();
        String stringValue();
    }

    // Kotlin代碼,命名參數(shù)傳遞注解參數(shù)
    @Ann(intValue = 1, stringValue = "abc") class C

2.在Java注解中,有一個特殊的value參數(shù)無需顯式指定參數(shù)名:
    // Java
    public @interface AnnWithValue {
        String value();
    }

    // Kotlin
    @AnnWithValue("abc") class C

3.如果Java注解的value參數(shù)類型是數(shù)組,那么在Kotlin中該參數(shù)類型就是vararg(參數(shù)個數(shù)可變):
    // Java
    public @interface AnnWithArrayValue {
        String[] value();
    }
    // Kotlin,參數(shù)類型是vararg(參數(shù)個數(shù)可變),相當(dāng)于數(shù)組
    @AnnWithArrayValue("abc", "foo", "bar") class C

4.如果Java注解的其它參數(shù)類型是數(shù)組,那么在Kotlin中該參數(shù)需要顯式使用arrayOf:
    // Java
    public @interface AnnWithArrayMethod {
        String[] names();
    }
    
    // Kotlin
    @AnnWithArrayMethod(names = arrayOf("abc", "foo", "bar")) class C

5.Java注解實例對象值會作為Kotlin屬性,暴露給Kotlin代碼:
    // Java
    public @interface Ann {
        int value();
    }

    // Kotlin
    fun foo(ann: Ann) {
        val i = ann.value
    }

簡書:http://www.lxweimin.com/p/7ec60cc61c7b
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/74781883
GitHub博客:http://lioil.win/2017/07/07/Kotlin-annotation.html
Coding博客:http://c.lioil.win/2017/07/07/Kotlin-annotation.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,892評論 2 372

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