如何在Kotlin数据类构造函数的参数与属性上同时找到指定注解?
Kotlin注解在主构造器属性与参数间自动同步的问题
为什么注解不会自动应用到所有适用目标?
在Kotlin中,当你在主构造器的属性声明(比如val i: Int)上标注注解时,默认的注解附着目标是构造器参数(VALUE_PARAMETER)——哪怕你的注解允许同时应用到属性(PROPERTY)和参数也一样。这是因为主构造器里的属性声明同时对应了两个独立的程序元素:构造器的入参,以及类的成员属性。Kotlin需要明确知道你要把注解挂到哪个元素上,不会自动将注解复制到所有允许的目标上。
对应你代码里的情况:
@Apple的目标仅为PROPERTY,所以标注在属性参数上时,只会附着到类属性Foo::i上,构造器参数找不到它。@Banana的目标仅为VALUE_PARAMETER,只会附着到构造器参数上,属性找不到。@Pear虽然允许两个目标,但默认只会附着到构造器参数上,所以Foo::i.findAnnotation<Pear>()拿不到,只有参数能获取到。@Orange没指定@Target,默认允许的目标包含PROPERTY和VALUE_PARAMETER,所以会同时出现在属性和参数上。
更简洁的实现方式
不想让用户手动写@param:Pear @property:Pear的话,可以通过以下方式解决:
封装反射工具类,自动关联属性与参数的注解
写一个通用工具函数,当查找属性的注解时,如果当前属性上找不到,就自动去对应的构造器参数里查找;反过来查找参数注解时,也会去对应的属性里兜底。示例代码:
import kotlin.reflect.KProperty import kotlin.reflect.KParameter import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.primaryConstructor // 查找属性注解,找不到则 fallback 到对应构造器参数 inline fun <reified T : Annotation> KProperty<*>.findAnnotationWithParamFallback(): T? { return this.findAnnotation<T>() ?: run { val constructor = this.declaringClass.primaryConstructor ?: return null constructor.parameters.firstOrNull { it.name == this.name }?.findAnnotation<T>() } } // 查找参数注解,找不到则 fallback 到对应属性 inline fun <reified T : Annotation> KParameter.findAnnotationWithPropertyFallback(): T? { return this.findAnnotation<T>() ?: run { val property = this.type.classifier as? Class<*> ?: return null property.kotlin.memberProperties.firstOrNull { it.name == this.name }?.findAnnotation<T>() } }
使用时直接调用封装后的方法,比如Foo::i.findAnnotationWithParamFallback<Pear>(),就能自动拿到参数上的Pear注解,不用用户重复标注。
如果是库开发者,还可以把这个工具类集成到库的API里,让用户完全不用关心底层的注解附着细节。
内容的提问来源于stack exchange,提问作者user717847
相关产品推荐
相关产品推荐

