Boris Treukhov
Boris Treukhov

Reputation: 17774

What is legitimate way to get annotations of a pure Kotlin property via reflection, are they always missing?

I'm trying to get annotations from Kotlin data class

package some.meaningless.package.name

import kotlin.reflect.full.memberProperties

annotation class MyAnnotation()

@MyAnnotation
data class TestDto(@MyAnnotation val answer: Int = 42)

fun main(args: Array<String>) {
    TestDto::class.memberProperties.forEach { p -> println(p.annotations) }
    println(TestDto::class.annotations)
}

I need to process class annotation to make a custom name serialization of GSON however no matter how I declare annotation class it never gets detected

The program always outputs

[] 
[@some.meaningless.package.name.MyAnnotation()]

which means only class level annotations are present

Upvotes: 1

Views: 926

Answers (2)

Boris Treukhov
Boris Treukhov

Reputation: 17774

Ok, it seems that the culprit was, that Kotlin annotations have default @Target(AnnotationTarget.CLASS) which is not stressed enough in documentation.

After I added @Target to the annotation class it now works properly

@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
annotation class MyAnnotation()

Now it prints out

[@some.meaningless.package.name.MyAnnotation()]
[@some.meaningless.package.name.MyAnnotation()]

As a side affect it will force the compiler to check that the annotation is applied as required, in current version of Kotlin, if explicit @Targetis not present only class level annotations are kept but no validity checks performed.

Upvotes: 4

holi-java
holi-java

Reputation: 30686

As Kotlin reference said as below:

If you don't specify a use-site target, the target is chosen according to the @Target annotation of the annotation being used. If there are multiple applicable targets, the first applicable target from the following: param > property > field.

To make the annotation annotated on a property, you should use site target, for example:

@MyAnnotation
data class TestDto(@property:MyAnnotation val answer: Int = 42)

However, annotations with property target in Kotlin are not visible to Java, so you should double the annotation, for example:

@MyAnnotation      // v--- used for property  v--- used for params in Java
data class TestDto(@property:MyAnnotation @MyAnnotation val answer: Int = 42)

Upvotes: 3

Related Questions