一、声明注解
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反射在首次使用时有性能问题