Reputation: 3310
In the following test, the field id
of class TestData
is marked with the annotation Foo
. Why is the output of .annotations
and .findAnnotation<Foo>()
empty though?
How can check if a field is annotated by a certain annotation?
(This is not the same question as How to list field annotations in Kotlin? where the asker forgot to change the retention to RUNTIME)
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.findAnnotation
import kotlin.test.Test
class MissingAnnotationTest {
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class Foo
data class TestData(@field:Foo val id: Int)
@Test
fun test() {
val obj = TestData(123)
val idProp = obj::class.declaredMemberProperties.first { it.name == "id" }
println("1 name: " + idProp) // "val ...TestData.id: kotlin.Int"
println("1 annotations: " + idProp.annotations) // [] - but why?
println("1 found @Foo: " + idProp.findAnnotation<Foo>()) // null - but why?
}
}
Upvotes: 3
Views: 2357
Reputation: 3310
I got a hint in the Kotlin discussion group and can now answer it myself:
A Kotlin "property" is compiled to a backing field and its getter/setter functions. If the target FIELD and not PROPERTY is used, the annotation is applied to the backing field. Pure backing fields do not exist in Kotlin though, therfore one has to access them via .javaField:
val idField = obj::class.memberProperties.first { it.name == "id" }.javaField!!
assertNotNull(idField.getAnnotation(Foo::class.java))
Upvotes: 6