Reflection Issues with Arrays

Hey all,

I have a problem when using reflections to create an instance of an object and then setting it as a member also through reflections. This problem only occurs with typed arrays. Here is a minimal viable code example showing my problem:

import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.memberProperties

data class DataClassWithArray (var array: Array<InnerArrayType> = arrayOf())
data class DataClass (var array: ArrayList<InnerArrayType> = arrayListOf())
data class InnerArrayType(val data: Int = 0)

fun main() {
    val dataClass = DataClass()

    dataClass::class.memberProperties.forEach { kProperty ->
        if (kProperty is KMutableProperty<*>) {
            val arrayList = arrayListOf((kProperty.returnType.arguments[0].type!!.classifier as KClass<*>).createInstance())
            println("Working with Kotlin class: ${arrayList::class} and java class ${arrayList::class.java.name}")
            kProperty.setter.call(dataClass, arrayList)
        }
    }

    val dataClassWithArray = DataClassWithArray()

    dataClassWithArray::class.memberProperties.forEach { kProperty ->
        if (kProperty is KMutableProperty<*>) {
            val array = arrayOf((kProperty.returnType.arguments[0].type!!.classifier as KClass<*>).createInstance())
            println("Failing with Kotlin class: ${array::class} and java class ${array::class.java.name}")
            kProperty.setter.call(dataClassWithArray, array)
        }
    }
}

The code results in the following output:

Working with Kotlin class: class java.util.ArrayList and java class java.util.ArrayList
Failing with Kotlin class: class kotlin.Array and java class [Ljava.lang.Object;
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97)
	at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113)
	at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:106)
	at TestKt.main(Test.kt:27)
	at TestKt.main(Test.kt)

Somehow the java class of the array is Object-Array instead of InnerArrayType-Array. This seems to lead to an error when trying to invoke the setter of the member through reflections. This only occurs with arrays. Is this behavior intentional? I couldn’t find any documentation about it.

This looks like the same issue as this
This is because when you call arrayOf with an unknown type, you construct an Array<Object>, and Arrays inheritely store their type inside, so you can’t use an Array<Object> as an Array<InnerArrayType> even if all the elements are of that type
What you instead need is something like:

fun <T> KClass<T>.arrayOf(vararg elements: T): Array<T> = elements.copyInto(java.lang.reflect.Array.newInstance(this, elements.size)) as Array<T>