Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call class' constructor by reflection with Kotlin

I have the following data class

data class Person (val id: Int? = null, val name: String, val active: Boolean)

I need to call it's constructor by reflection. I tried the following code

private fun <T> createEntity(constructor: Constructor<*>, vararg args: T) : Any {
    return constructor.newInstance(args)
}

and call it with an array for the args parameter.

val fields = entity.declaredFields
var elements = Array<Any>(getFieldsCount(fields), { i ->
    val index = cursor.getColumnIndex(fields[i].name.toUpperCase())
    when (fields[i].type) {
        kotlin.Int::class.java -> cursor.getInt(index)
        kotlin.Boolean::class.java -> if (cursor.getInt(index) == 1) true else false
        else -> cursor.getString(index)
    }

})
val test = createEntity(entity.constructors.first(), *elements)

With entity: Class<T> and cursor: Cursor from a local database Kotlin Documentation says :

When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *)

but even with the * I keep getting the following exception :

java.lang.IllegalArgumentException: Wrong number of arguments; expected 3, got 1

Can anyone give me some tips on how to instantiate my class? Thanks

like image 353
tufekoi Avatar asked Apr 16 '16 13:04

tufekoi


People also ask

How do I call a constructor from another class in Kotlin?

In Kotlin, one secondary constructor can call another secondary constructor of same class. This is done by using this() keyword. For example: class myClass{

How do I call a constructor in Kotlin?

In Kotlin, you can also call a constructor from another constructor of the same class (like in Java) using this() .

Does Kotlin support reflection?

In libraries like Retrofit or Kotlin-serialization, you define a bunch of classes or interfaces and annotate them with some predefined keywords and it works perfectly in the runtime. The same is true for Android.

What is KClass in Kotlin?

The KClass type is Kotlin's counterpart to Java's java. lang. Class type. It's used to hold references to Kotlin classes; you'll see what it lets you do with those classes in the “Reflection” section later in this chapter. The type parameter of KClass specifies which Kotlin classes can be referred to by this reference.


1 Answers

You have to use the spread operator when invoking the newInstance() method. And the signature of createEntity() is wrong. I would recommend define it like that.

private fun <T> createEntity(constructor: Constructor<T>, vararg args: Any) : T {
    return constructor.newInstance(*args)
}
like image 110
Michael Avatar answered Oct 19 '22 16:10

Michael