kotlin更多語言結構——>注解
注解聲明
注解是將元數據附加到代碼的方法。要聲明注解,請將 annotation 修飾符放在類的前面
annotation class Fancy
注解的附加屬性可以通過用元注解標注注解類來指定
— @Target指定可以用該注解標注的元素的可能的類型(類、函數、屬性、表達式等);
— @Retention指定該注解是否存儲在編譯后的class文件中,以及它在運行時能否通過反射可?(默認都是 true);
— @Repeatable允許在單個元素上多次使用相同的該注解;
— @MustBeDocumented指定該注解是公有API的一部分,并且應該包含在生成的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)
}
}
如果需要對類的主構造函數進行標注,則需要在構造函數聲明中添加 constructor 關鍵字 ,并將注解添加到 其前面
class Foo @Inject constructor(dependency: MyDependency) { ...... }
你也可以標注屬性訪問器
class Foo {
var x: MyDependency? = null
@Inject set
}
構造函數
注解可以有接受參數的構造函數
annotation class Special(val why: String)
@Special("example") class Foo {}
允許的參數類型有
— 對應于Java原生類型的類型(Int、Long等); — 字符串;
— 類(Foo::class);
— 枚舉;
— 其他注解;
— 上面已列類型的數組。
注解參數不能有可空類型,因為 JVM 不支持將 null 作為注解屬性的值存儲。
如果注解用作另一個注解的參數,則其名稱不以 @ 字符為前綴
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"))
如果需要將一個類指定為注解的參數,請使用 Kotlin 類(KClass)。Kotlin 編譯器會自動將其轉換為 Java 類,以 便 Java 代碼能夠正常訪問該注解與參數
import kotlin.reflect.KClass annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any>) @Ann(String::class, Int::class) class MyClass
Lambda 表達式
注解也可以用于 lambda 表達式。它們會被應用于生成 lambda 表達式體的 invoke() 方法上。這對于像Quasar 這樣的框架很有用,該框架使用注解進行并發控制
annotation class Suspendable
val f = @Suspendable { Fiber.sleep(10) }
注解使用處目標
當對屬性或主構造函數參數進行標注時,從相應的 Kotlin 元素生成的 Java 元素會有多個,因此在生成的 Java 字節碼中該注解有多個可能位置 。如果要指定精確地指定應該如何生成該注解,請使用以下語法
class Example(
@field:Ann val foo,// 標注 Java 字段
@get:Ann val bar,// 標注 Java getter
@param:Ann val quux// 標注 Java 構造函數參數
)
可以使用相同的語法來標注整個文件。要做到這一點,把帶有目標 file 的注解放在文件的頂層、package 指 令之前或者在所有導入之前(如果文件在默認包中的話)
@file:JvmName("Foo")
package org.jetbrains.demo
如果你對同一目標有多個注解,那么可以這樣來避免目標重復——在目標后面添加方括號并將所有注解放在方 括號內
class Example {
@set:[Inject VisibleForTesting]
var collaborator: Collaborator
}
支持的使用處目標的完整列表為
— file;
— property(具有此目標的注解對 Java 不可?);
— field ;
— get(屬性 getter);
— set(屬性 setter);
— receiver(擴展函數或屬性的接收者參數);
— param(構造函數參數);
— setparam(屬性 setter 參數);
— delegate(為委托屬性存儲其委托實例的字段)
要標注擴展函數的接收者參數,請使用以下語法
fun @receiver:Fancy String.myExtension() { ... }
如果不指定使用處目標,則根據正在使用的注解的 @Target 注解來選擇目標 。如果有多個適用的目標,則使用以下列表中的第一個適用目標
— 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 注解應用于屬性 getter
@get:Rule val tempFolder = TemporaryFolder()
@Test fun simple() {
val f = tempFolder.newFile()
assertEquals(42, getTheAnswer())
}
}
因為 Java 編寫的注解沒有定義參數順序,所以不能使用常規函數調用語法來傳遞參數。相反,你需要使用具名參 數語法
// Java
public @interface Ann {
int intValue();
String stringValue();
}
// Kotlin @Ann(intValue = 1, stringValue = "abc") class C
就像在 Java 中一樣,一個特殊的情況是 value 參數;它的值無需顯式名稱指定
// Java
public @interface AnnWithValue {
String value();
}
// Kotlin
@AnnWithValue("abc") class C
數組作為注解參數
如果 Java 中的 value 參數具有數組類型,它會成為 Kotlin 中的一個 vararg 參數
// Java
public @interface AnnWithArrayValue {
String[] value();
}
// Kotlin
@AnnWithArrayValue("abc", "foo", "bar") class C
對于具有數組類型的其他參數,你需要顯式使用數組字面值語法(自 Kotlin 1.2 起)或者 arrayOf(......)
// Java
public @interface AnnWithArrayMethod {
String[] names();
}
/ Kotlin 1.2+:
@AnnWithArrayMethod(names = ["abc", "foo", "bar"])
class C
// 舊版本 Kotlin:
@AnnWithArrayMethod(names = arrayOf("abc", "foo", "bar"))
class D
訪問注解實例的屬性
注解實例的值會作為屬性暴露給 Kotlin 代碼
// Java
public @interface Ann {
int value();
}
// Kotlin
fun foo(ann: Ann) {
val i = ann.value
}

浙公網安備 33010602011771號