7

Using Kotlin reflection, I am trying to check the KClass of each parameter of a class's primary constructor.

Given a simple data class like this:

data class MyPerson(val name: String, val age: Int)
val modelClass = MyPerson::class

I get its primary constructor val primaryConstructor = modelClass.primaryConstructor. For each parameter, I want to check its class (is it Kotlin.String, Kotlin.Int etc). Something like this:

for (param in primaryConstructor.parameters) {
  when(param.type) {
    is Kotlin.String -> // do string thing
    is Kotlin.Int -> // do int thing
}

Unfortunately, this isn't valid code. I've tried param.type, param.classifier, param.type.jvmErasure and others. The closest I've found is param.type.jvmErasure.qualifiedName, which gives me a String with the fully qualified name of the KClass. But I really want the KClass.

Is this possible at all?

ljd
  • 75
  • 1
  • 8

3 Answers3

10

The param.type expression returns a KType, so you need to get the appropriate Ktype instances to check against:

for (param in primaryConstructor.parameters) {
    when (param.type) {
        String::class.createType() -> println("String param")
        Int::class.createType() -> println("Int param")
    }
}

Side note: might be a good idea to not create these every time in the loop:

val stringType = String::class.createType()
val intType = Int::class.createType()
for (param in primaryConstructor.parameters) {
    when (param.type) {
        stringType -> println("String param")
        intType -> println("Int param")
    }
}
zsmb13
  • 85,752
  • 11
  • 221
  • 226
4

You can use the javaType property of KType for that comparison:

when (param.type.javaType) {
    String::class.java -> println("String!")
    Int::class.java -> println("Int!")
}
s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
0

Use the unsafe cast operator as:

val kClass: KClass<*> = param.type.classifier as KClass<*>
RJ.Hwang
  • 1,683
  • 14
  • 24