一、聲明注解
Kotlin聲明注解的方式與Java略有不同,只需要在class前使用annotation修飾。
annotation class Foo
同Java一樣,可以通過元注解來標記自定義的注解
@Target(AnnotationTarget.PROPERTY)
annotation class Foo
1. 元注解@Target
AnnotationTarget枚舉了所有Kotlin注解可應用到的目標
2. 元注解@Retention
@Retention元注解用來表示你聲明的注解是否會保存到.class文件,以及運行時是否可通過反射來訪問他。
與Java不同,Kotlin注解默認擁有RUNTIME保留期
既
@Target(AnnotationTarget.PROPERTY)
annotation class Foo
等價於
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME) // 默認為RUNTIME,可以省略
annotation class Foo
二、使用注解
Kotlin中的注解使用和Java沒有太大的區別,需要注意的是:Kotlin中的類的屬性對應Java中類的多個元素
class A() {
var name: String? = null
}
等價於java
public class A {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
所以,在使用Kotlin注解時,通過@目標:注解
的語法,可以明確指定注解的目標,來自官網的例子
@Target(
AnnotationTarget.PROPERTY,
AnnotationTarget.FUNCTION,
AnnotationTarget.FIELD,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.PROPERTY_GETTER
)
annotation class Ann
class Example(
@field:Ann val foo: String, // 注解 Java類的字段
@get:Ann val bar: String, // 注解 Java getter
@param:Ann val quux: String // 注解 Java 構造函數的參數
)
所以使用Java注解,在屬性上對應的目標自然是field
三、通過反射獲得注解信息
在Kotlin中通過反射獲取java信息十分方便,但需要注意,作用在不同目標的注解獲取方式有差異
要使用反射,首先需要引入kotlin-reflect: https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-reflect
println(Example::foo.annotations)// 獲取 @property: 修飾的注解
println(Example::foo.findAnnotation<Ann>())// 獲取 @property: 修飾的注解
println(Example::foo.getter.annotations) // 獲取 @get: 修飾的注解
println(Example::foo.getter.findAnnotation<Ann>())// 獲取 @get: 修飾的注解
println(Example::foo.javaField?.annotations) // java方式獲取注解信息,獲取 @field: 修飾的注解以及原生java注解
println(Example::foo.javaField?.getAnnotation(Ann::class.java))// java方式獲取注解信息,獲取 @field: 修飾的注解以及原生java注解
// 以此類推......
Kotlin中的findAnnotation方法利用inline
函數及reified
,可以通過指定泛型的類型來獲取對應注解,十分方便,我們也可以自己實現一個獲取@field:
注解的findFieldAnnotation方法
inline fun <reified T : Annotation> KProperty<*>. findFieldAnnotation(): T? {
return javaField?.getAnnotation(T::class.java)
}
要注意Kotlin反射在首次使用時有性能問題