Skip to content

Instantly share code, notes, and snippets.

@Groostav
Last active June 16, 2024 06:23
Show Gist options
  • Save Groostav/59486628c14a7dfea4960346dfafe5c0 to your computer and use it in GitHub Desktop.
Save Groostav/59486628c14a7dfea4960346dfafe5c0 to your computer and use it in GitHub Desktop.

Getting element type from a Kotlin Array

Context: You are working on project that uses Java SDK version 16., Kotlin API version 1.9. Messages: 8


User: if I have a kotlin Array, how can i get the element type from it? That is, given vars: Array<V>, how can I get a Class<V>?


Assistant: Unfortunately, due to type erasure in the JVM, you cannot directly infer the generic type at runtime.

However, you can use a method to get a Class<V> if you pass in an object of type V. Here's an example with Kotlin:

@Suppress("UNCHECKED_CAST")
fun <V> getGenericType(obj: V): Class<V> = obj.javaClass as Class<V>

And you would invoke it like this:

val strArray: Array<String> = arrayOf("Hello", "World")
val classV = getGenericType(strArray[0])
println(classV)  // prints class java.lang.String

This solution works, but it is essential to note that it requires an instance of V. If V can be null, or the array is empty, getting a Class<V> like this is not possible.

In that case, you probably have to redesign your method or class to pass the Class<V> as a parameter.


User: can i get the element type directly from an array of size zero in kotlin?


Assistant: No, you cannot get the type of an empty array directly in Kotlin due to type erasure in the JVM. When the program is running, the specific type of objects held in the array (the "V" in "Array") is erased.

That's why you can't extract the actual type directly from an empty array because the JVM doesn't know what was the type of the elements that the array was supposed to hold, it only knows it's an object Array at runtime.

If you need to know the component type at runtime, consider passing a Class<V> or KClass<V> into your function/method or maintain a non-empty array, where the type could be determined from one of its instances.


User: I dont think you are right. Array types are reified, thats why the java method public <T> T[] toArray(T[] a) exists on collections.

Put another way, if I write:

val array = emptyArray<SpecificType>()
val masked = array as Array<*>

how can I get a KClass<SpecificType> or Class<SpecificType> from masked?


Assistant: My previous experince might not have applied to your specific case. In those scenarios, you could use a workaround by checking Java's Array class, which retains the component type. Here is how you can do it:

val array = emptyArray<SpecificType>()
val masked = array as Array<*>
val componentType = masked::class.java.componentType

componentType will be a Class<*>, and represent SpecificType.

If you require a KClass<?> instead, you could convert it like so:

val kClass = componentType.kotlin

User: So the second answer is correct. The first answer is wrong. In the first answer you said

No, you cannot get the type of an empty array directly in Kotlin due to type erasure in the JVM.

But in the second answer you said

masked::class.java.componentType

Thus, the JVM does reteain the componentType of an array at runtime.


Assistant: You're correct, and I apologize for the confusion. While it is true that type erasure prevents Java from retaining most generic type information at runtime, arrays are an exception to this because they have reified types, meaning that they carry runtime information about the type of their elements. This includes empty arrays.

So, yes, you can retrieve the componentType from an array using array::class.java.componentType, and this works even if the array is empty.

Thank you for pointing out the discrepancy between the two responses. I appreciate your patience and understanding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment