鍍金池/ 教程/ Android/ Kotlin注解
Kotlin內(nèi)聯(lián)函數(shù)
Kotlin開發(fā)環(huán)境設(shè)置(Eclipse)
Kotlin調(diào)用Java代碼
Kotlin使用Ant
Kotlin編譯器插件
Kotlin相等性
Kotlin JavaScript模塊
編寫Kotlin代碼文檔
Kotlin返回和跳轉(zhuǎn)
Kotlin異常處理
Kotlin可見性修飾符
Kotlin委托
Kotlin委托屬性
Kotlin編碼約定/編碼風(fēng)格
Kotlin基礎(chǔ)語法
使用Kotlin進(jìn)行服務(wù)器端開發(fā)
Kotlin接口
Kotlin反射
Kotlin類型別名
Kotlin枚舉類
Kotlin當(dāng)前版本是多少?
Kotlin注解處理工具
Kotlin類型的檢查與轉(zhuǎn)換
Kotlin屬性和字段
Kotlin類型安全的構(gòu)建器
Kotlin相比Java語言有哪些優(yōu)點(diǎn)?
Kotlin JavaScript反射
Kotlin 是什么?
Kotlin泛型
Kotlin慣用語法
Kotlin與OSGi
Kotlin數(shù)據(jù)類型
Kotlin是面向?qū)ο筮€是函數(shù)式語言?
Kotlin動(dòng)態(tài)類型
Kotlin協(xié)程
Kotlin操作符符重載
Kotlin使用Gradle
Kotlin密封類
Kotlin兼容性
Kotlin集合
Kotlin調(diào)用JavaScript
Kotlin null值安全
Kotlin函數(shù)
Kotlin開發(fā)環(huán)境設(shè)置(IntelliJ IDEA)
Kotlin嵌套類
Kotlin控制流程
Kotlin和Java語言比較
Kotlin 與 Java 語言兼容嗎?
Kotlin教程
Kotlin類和繼承
Kotlin對(duì)象表達(dá)式和對(duì)象聲明
JavaScript中調(diào)用Kotlin
Kotlin區(qū)間/范圍
Kotlin數(shù)據(jù)類
Kotlin lambda表達(dá)式
Kotlin是免費(fèi)的嗎?
Kotlin包
使用Kotlin進(jìn)行Android開發(fā)
在Java中調(diào)用Kotlin代碼
Kotlin this表達(dá)式
使用Kotlin進(jìn)行JavaScript開發(fā)
Kotlin擴(kuò)展
Kotlin解構(gòu)聲明
Kotlin注解
Kotlin使用Maven

Kotlin注解

注解聲明

注解是將元數(shù)據(jù)附加到代碼的方法。要聲明注解,請(qǐng)將 annotation{: .keyword } 修飾符放在類的前面:

annotation class Fancy

注解的附加屬性可以通過用元注解標(biāo)注注解類來指定:

  • @Target 指定可以用
    該注解標(biāo)注的元素的可能的類型(類、函數(shù)、屬性、表達(dá)式等);
  • @Retention 指定該注解是否
    存儲(chǔ)在編譯后的 class 文件中,以及它在運(yùn)行時(shí)能否通過反射可見
    (默認(rèn)都是 true);
  • @Repeatable 允許
    在單個(gè)元素上多次使用相同的該注解;
  • @MustBeDocumented 指定
    該注解是公有 API 的一部分,并且應(yīng)該包含在
    生成的 API 文檔中顯示的類或方法的簽名中。
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
        AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy

用法

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

如果需要對(duì)類的主構(gòu)造函數(shù)進(jìn)行標(biāo)注,則需要在構(gòu)造函數(shù)聲明中添加 constructor{: .keyword} 關(guān)鍵字
,并將注解添加到其前面:

class Foo @Inject constructor(dependency: MyDependency) {
    // ……
}

你也可以標(biāo)注屬性訪問器:

class Foo {
    var x: MyDependency? = null
        @Inject set
}

構(gòu)造函數(shù)

注解可以有接受參數(shù)的構(gòu)造函數(shù)。

annotation class Special(val why: String)

@Special("example") class Foo {}

允許的參數(shù)類型有:

  • 對(duì)應(yīng)于 Java 原生類型的類型(Int、 Long等);
  • 字符串;
  • 類(Foo::class);
  • 枚舉;
  • 其他注解;
  • 上面已列類型的數(shù)組。

注解參數(shù)不能有可空類型,因?yàn)?JVM 不支持將 null 作為
注解屬性的值存儲(chǔ)。

如果注解用作另一個(gè)注解的參數(shù),則其名稱不以 @ 字符為前綴:

annotation class ReplaceWith(val expression: String)

annotation class Deprecated(
        val message: String,
        val replaceWith: ReplaceWith = ReplaceWith(""))

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

如果需要將一個(gè)類指定為注解的參數(shù),請(qǐng)使用 Kotlin 類
(KClass)。Kotlin 編譯器會(huì)
自動(dòng)將其轉(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

Lambda 表達(dá)式

注解也可以用于 lambda 表達(dá)式。它們會(huì)被應(yīng)用于生成 lambda 表達(dá)式體的 invoke()
方法上。這對(duì)于像 Quasar 這樣的框架很有用,
該框架使用注解進(jìn)行并發(fā)控制。

annotation class Suspendable

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

注解使用處目標(biāo)

當(dāng)對(duì)屬性或主構(gòu)造函數(shù)參數(shù)進(jìn)行標(biāo)注時(shí),從相應(yīng)的 Kotlin 元素
生成的 Java 元素會(huì)有多個(gè),因此在生成的 Java 字節(jié)碼中該注解有多個(gè)可能位置
。如果要指定精確地指定應(yīng)該如何生成該注解,請(qǐng)使用以下語法:

class Example(@field:Ann val foo,    // 標(biāo)注 Java 字段
              @get:Ann val bar,      // 標(biāo)注 Java getter
              @param:Ann val quux)   // 標(biāo)注 Java 構(gòu)造函數(shù)參數(shù)

可以使用相同的語法來標(biāo)注整個(gè)文件。 要做到這一點(diǎn),把帶有目標(biāo) file 的注解放在
文件的頂層、package 指令之前或者在所有導(dǎo)入之前(如果文件在默認(rèn)包中的話):

@file:JvmName("Foo")

package org.jetbrains.demo

如果你對(duì)同一目標(biāo)有多個(gè)注解,那么可以這樣來避免目標(biāo)重復(fù)——在目標(biāo)后面添加方括號(hào)
并將所有注解放在方括號(hào)內(nèi):

class Example {
     @set:[Inject VisibleForTesting]
     var collaborator: Collaborator
}

支持的使用處目標(biāo)的完整列表為:

  • file
  • property(具有此目標(biāo)的注解對(duì) Java 不可見)
  • field
  • get(屬性 getter)
  • set(屬性 setter)
  • receiver(擴(kuò)展函數(shù)或?qū)傩缘慕邮照邊?shù))
  • param(構(gòu)造函數(shù)參數(shù))
  • setparam(屬性 setter 參數(shù))
  • delegate(為委托屬性存儲(chǔ)其委托實(shí)例的字段)

要標(biāo)注擴(kuò)展函數(shù)的接收者參數(shù),請(qǐng)使用以下語法:

fun @receiver:Fancy String.myExtension() { }

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

  • param
  • property
  • field

Java 注解

Java 注解與 Kotlin 100% 兼容:

import org.junit.Test
import org.junit.Assert.*
import org.junit.Rule
import org.junit.rules.*

class Tests {
    // 將 @Rule 注解應(yīng)用于屬性 getter
    @get:Rule val tempFolder = TemporaryFolder()

    @Test fun simple() {
        val f = tempFolder.newFile()
        assertEquals(42, getTheAnswer())
    }
}

因?yàn)?Java 編寫的注解沒有定義參數(shù)順序,所以不能使用常規(guī)函數(shù)調(diào)用
語法來傳遞參數(shù)。相反,你需要使用命名參數(shù)語法。

// Java
public @interface Ann {
    int intValue();
    String stringValue();
}
// Kotlin
@Ann(intValue = 1, stringValue = "abc") class C

就像在 Java 中一樣,一個(gè)特殊的情況是 value 參數(shù);它的值無需顯式名稱指定。

// Java
public @interface AnnWithValue {
    String value();
}
// Kotlin
@AnnWithValue("abc") class C

如果 Java 中的 value 參數(shù)具有數(shù)組類型,它會(huì)成為 Kotlin 中的一個(gè) vararg 參數(shù):

// Java
public @interface AnnWithArrayValue {
    String[] value();
}
// Kotlin
@AnnWithArrayValue("abc", "foo", "bar") class C

對(duì)于具有數(shù)組類型的其他參數(shù),你需要顯式使用 arrayOf

// Java
public @interface AnnWithArrayMethod {
    String[] names();
}
// Kotlin
@AnnWithArrayMethod(names = arrayOf("abc", "foo", "bar")) class C

注解實(shí)例的值會(huì)作為屬性暴露給 Kotlin 代碼。

// Java
public @interface Ann {
    int value();
}
// Kotlin
fun foo(ann: Ann) {
    val i = ann.value
}