问题
I have a simple TYPE_USE
annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Cool {
}
And the following sample Kotlin class:
class Item(
id: Long? = null,
var names: List<@Cool String> = emptyList())
Is there any way to extract the annotation using Java reflection?
Item.class.getMethod("getName").getAnnotatedReturnType()
loses the annotations, same with getting the field.
Can I even get the annotation from Kotlin?
Item::class.memberProperties.elementAt(0).returnType
return a KType
which has the annotation, but I don't see a way to extract it. Nor to obtain an AnnotatedType
from KType
, even though I have JDK8 extensions.
All I see is KType#javaType
but this returns Type
, not AnnotatedType
... so it looses the annotations again.
回答1:
Edit: this is a bug and has been reported. There is not yet a target version, but its priority has been set to Major. This was fixed in Kotlin 1.3.
TL; DR: no...?
The item annotated with @Cool
is the first type argument, so you need to retrieve it:
val type = Item::class.memberProperties.elementAt(0).returnType
val arg = type.arguments[0]
println(arg) // KTypeProjection(variance=INVARIANT, type=@Cool kotlin.String)
Unfortunately there doesn't seem to be a way to retrieve the annotations on a KType
(as you have mentioned).
Strangely, this is a very internal process. Looking into the source for KTypeImpl shows that toString
is implemented via ReflectionObjectRenderer.renderType(type)
, (where type is a KotlinType
) which is delegated to DescriptorRenderer.FQ_NAMES_IN_TYPES
, which we can see is a DescriptorRenderer with modifiers ALL.
The renderer checks if the type is a subclass of kotlin.reflect.jvm.internal.impl.descriptors.annotations.Annotated
, and then accesses its annotations
property.
I tried this:
val retType = Item::class.memberProperties.elementAt(0).returnType
val arg = retType.arguments[0]
println(arg) // KTypeProjection(variance=INVARIANT, type=@Cool kotlin.String)
val type = arg.type!!
println(type)
val field = type::class.memberProperties.first { it.name == "type" }
val kotlinType = field.call(type) as Annotated
println(kotlinType)
println(kotlinType.annotations)
Unfortunately, I get a ClassNotFoundException
for org.jetbrains.kotlin.types.KotlinType
, so that option is gone.
Equally strangely, KType
is not a subtype of KAnnotatedElement
(which is why it has no annotations
property).
I suppose this may have been an oversight, since KTypeImpl
wraps a KotlinType
, which does contain annotations.
来源:https://stackoverflow.com/questions/48948311/retrieve-annotations-from-ktype