Kotlin通过反射读取属性注释

Kotlin通过反射读取属性注释,kotlin,reflection,properties,annotations,Kotlin,Reflection,Properties,Annotations,我已经为属性创建了一个注释,现在我想在运行时通过反射来读取它。在我看来,我做的每件事都是对的,但没有任何注释 为什么注释不可用 @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) annotation class MyAnnotation class MyClass(@MyAnnotation val attr: List<

我已经为属性创建了一个注释,现在我想在运行时通过反射来读取它。在我看来,我做的每件事都是对的,但没有任何注释

为什么注释不可用

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
annotation class MyAnnotation

class MyClass(@MyAnnotation val attr: List<String>)

fun main(args: Array<String>) {
    var prop = MyClass::attr
    prop.annotations.forEach { println("prop.annotations -> " + it) }
    prop.javaClass.getAnnotations().forEach { println("prop.javaClass.getAnnotations -> " + it) }
    println("isAnnotationPresent -> ${prop.javaClass.isAnnotationPresent(MyAnnotation::class.java)}")
}
输出: prop.javaClass.getAnnotations->@kotlin.Metadataxi=0,bv=[1,0,3],mv=[1,1,16],k=3,xs=,d1=[],d2=[],pn= isAnnotationPresent->false

As

如果未指定使用站点目标,则将根据所用注释的@target注释选择目标。如果存在多个适用目标,则使用以下列表中的第一个适用目标:

param

财产

因此,在您的例子中,注释的是参数,而不是属性。根据您的要求,您可以通过检查属性和参数注释来解决此问题:

val param = MyClass::class.primaryConstructor.findParameterByName(prop.name)
val annotations = prop.annotations + (param?.annotations ?: listOf())
作为

如果未指定使用站点目标,则将根据所用注释的@target注释选择目标。如果存在多个适用目标,则使用以下列表中的第一个适用目标:

param

财产

因此,在您的例子中,注释的是参数,而不是属性。根据您的要求,您可以通过检查属性和参数注释来解决此问题:

val param = MyClass::class.primaryConstructor.findParameterByName(prop.name)
val annotations = prop.annotations + (param?.annotations ?: listOf())

您可以将注释目标指定为@TargetAnnotationTarget.FIELD并按如下方式访问,而不是将注释目标指定为@TargetAnnotationTarget.PROPERTY、AnnotationTarget.VALUE_参数:

@Target(AnnotationTarget.FIELD)
annotation class MyAnnotation

class MyClass(@MyAnnotation val attr: String)

fun main(args: Array<String>) {
    val prop = MyClass::attr
    println("Is MyAnnotation annotated - ${prop.javaField?.isAnnotationPresent(MyAnnotation::class.java)}")
    prop.javaField?.annotations?.forEach { println("Annotation present is - ${it.annotationClass.qualifiedName}") }
}
输出:

MyAnnotation是否注释为-true

当前的批注为-packageName.MyAnnotation


您可以将注释目标指定为@TargetAnnotationTarget.FIELD并按如下方式访问,而不是将注释目标指定为@TargetAnnotationTarget.PROPERTY、AnnotationTarget.VALUE_参数:

@Target(AnnotationTarget.FIELD)
annotation class MyAnnotation

class MyClass(@MyAnnotation val attr: String)

fun main(args: Array<String>) {
    val prop = MyClass::attr
    println("Is MyAnnotation annotated - ${prop.javaField?.isAnnotationPresent(MyAnnotation::class.java)}")
    prop.javaField?.annotations?.forEach { println("Annotation present is - ${it.annotationClass.qualifiedName}") }
}
输出:

MyAnnotation是否注释为-true

当前的批注为-packageName.MyAnnotation


您是否有任何使用VALUE_参数target的具体原因?您是对的。如果没有“目标值”参数,注释将显示在“注释”列表中。为什么?你使用VALUE_参数target有什么具体的原因吗?你是对的。如果没有“目标值”参数,注释将显示在“注释”列表中。为什么?这对@Jayser有帮助吗?我不得不用javaClass替换javaField,但它不起作用。@Jayser不,你不应该使用javaClass,而是按照我的回答使用javaField。作为我答案的一部分的代码片段运行良好。请试一试。我使用Kotlin 1.3.61,我得到一个未解决引用的编译时错误:javaFieldkotlin reflect也被添加到我的maven依赖项中。我不知道为什么javaField属性不可用。这对@Jayser有帮助吗?我不得不用javaClass替换javaField,但它不起作用。@Jayser不,你不应该使用javaClass,而是按照我的回答使用javaField。作为我答案的一部分的代码片段运行良好。请试一试。我使用Kotlin 1.3.61,我得到一个未解决引用的编译时错误:javaFieldkotlin reflect也被添加到我的maven依赖项中。我不知道为什么javaField属性不可用。