Kotlin运行时通过反射读取属性注解失败原因排查
问题分析与解决方案
你的问题出在两个关键地方:一是错误地获取了KProperty类自身的注解,而非目标属性的注解;二是默认情况下,你加在主构造函数参数上的注解并没有绑定到Kotlin属性本身,而是绑定到了构造函数参数上。
为什么当前代码拿不到注解?
- 你用
prop.javaClass.getAnnotations()获取的是KProperty这个类的注解(比如输出里的@kotlin.Metadata),这和你定义的MyAnnotation完全无关,属于反射对象的混淆使用。 - 当你在主构造函数的
val attr上写@MyAnnotation时,尽管你的注解@Target包含PROPERTY和VALUE_PARAMETER,但Kotlin默认会将注解应用到构造函数参数(VALUE_PARAMETER),而不是Kotlin属性(PROPERTY)。所以prop.annotations自然是空的。
解决方法一:显式指定注解应用到属性
如果你希望注解绑定到Kotlin属性本身,可以在注解前加上@property:前缀,这样就能通过KProperty.annotations直接获取:
@Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) annotation class MyAnnotation class MyClass(@property:MyAnnotation val attr: List<String>) fun main(args: Array<String>) { val prop = MyClass::attr prop.annotations.forEach { println("prop.annotations -> $it") } // 输出:prop.annotations -> @MyAnnotation() }
解决方法二:从构造函数参数中获取注解
如果你需要保留注解在构造函数参数上的绑定,可以通过类的主构造函数参数列表来获取:
@Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) annotation class MyAnnotation class MyClass(@MyAnnotation val attr: List<String>) fun main(args: Array<String>) { // 获取主构造函数,为空则直接返回 val constructor = MyClass::class.primaryConstructor ?: return // 遍历构造函数参数,输出对应注解 constructor.parameters.forEach { param -> param.annotations.forEach { println("constructor param annotation -> $it") } } // 输出:constructor param annotation -> @MyAnnotation() }
额外补充:如果你希望注解同时绑定到属性和构造函数参数,可以同时添加两个前缀:@property:MyAnnotation @MyAnnotation val attr: List<String>,这样两种反射方式都能获取到注解。
内容的提问来源于stack exchange,提问作者Jayser
相关产品推荐
相关产品推荐

