Matthew Layton
Matthew Layton

Reputation: 42390

Kotlin - determine nested generic types at runtime

I have the following classes in my solution

open class State<T : Any> { ... }

class CustomState : State<BigDecimal> { ... }

abstract class FindState<T : State<*>> { ... }

class FindStateImpl<T : State<*>> : FindState<T>() { ... }

FindState may be called like so

val strState = FindStateImpl<State<String>>(...)

val intState = FindStateImpl<State<Int>>(...)

val customState = FindStateImpl<CustomState>(...)

From inside the FindState class I need to be able to obtain at runtime, the the class types for:

Thus for the examples above I would need to obtain:

val strState = FindStateImpl<State<String>>(...)
//State::class.java
//String::class.java

val intState = FindStateImpl<State<Int>>(...)
//State::class.java
//Int::class.java

val customState = FindStateImpl<CustomState>(...)
//CustomState::class.java
//BigDecimal::class.java (since string is the underlying type T)

So far I've got something like this, but it's hideous and doesn't fully work:

val stateType = javaClass.kotlin.supertypes[0].arguments[0].type?.jvmErasure?.javaObjectType

Is it possible to obtain these types at runtime?

Upvotes: 0

Views: 423

Answers (1)

Kiskae
Kiskae

Reputation: 25613

The code as you've provided simply doesn't contain the type information required since it will be erased. Only the subtypes that specify a specific type as part of the supertype are available.

With kotlin there are two ways to retrieve the type information:

  1. Use a pattern like Guava's TypeToken and make sure you provide an anonymous object that contains the required type information. This will make the reflection code work.
  2. Use a reified method and the typeOf<T>() method to embed the KType during compilation:
inline fun <reified T : Any, CS : State<T>> FindStateEmbedType(state: CS): FindState<CS> {
    val contentType = typeOf<T>();
    // Do what you need to do with T, perhaps embed in a wrapper FindState type
    return FindStateImplWithType(state, contentType)
}

Upvotes: 2

Related Questions