官方文檔: 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