在Kotlin中使用Kotlin/java注解及注意事项

一、声明注解

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反射在首次使用时有性能问题

原文地址:https://www.cnblogs.com/kevin-zjy-blog/p/14281470.html