问题
I am running some experiments on Kotlin's reflection.
I am trying to get a reflection object of a generic class with its argument.
In Java, that would be a ParameterizedType.
The way to get such a thing using Java's reflection API is a bit convoluted: create an anonymous subclass of a generic class, then get its super-type first parameter.
Here's an example:
@Suppress("unused") @PublishedApi
internal abstract class TypeReference<T> {}
inline fun <reified T> jGeneric() =
((object : TypeReference<T>() {}).javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
When I println(jGeneric<List<String?>>()), it prints java.util.List<? extends java.lang.String>, which is logical considering that Kotlin's List uses declaration-site out variance and that Java types have no notion of nullability.
Now, I would like to achieve the same kind of result, but with the Kotlin reflection API (that would, of course, contain nullability information).
Of course, List<String>::class cannot work since it yields a KClass. and I am looking for a KType.
However, when I try this:
inline fun <reified T> kGeneric() =
(object : TypeReference<T>() {})::class.supertypes[0].arguments[0].type
When I println(kGeneric<List<String?>>()), it prints [ERROR : Unknown type parameter 0], which is quite... well, anticlimactic ;)
How can I get, in Kotlin, a KType reflecting List<String> ?
回答1:
To create a KType instance in Kotlin 1.1, you have two options:
To create a simple non-nullable type out of a
KClass, where the class is either not generic or you can substitute all its type parameters with star projections (*), use thestarProjectedTypeproperty. For example, the following creates aKTyperepresenting a non-nullable typeString:val nonNullStringType = String::class.starProjectedTypeOr, the following creates a
KTyperepresenting a non-nullable typeList<*>:val nonNullListOfSmth = List::class.starProjectedTypeFor more complex cases, use the
createTypefunction. It takes the class, type arguments and whether or not the type should be nullable. Type arguments are a list ofKTypeProjectionwhich is simply a type + variance (in/out/none). For example, the following code creates aKTypeinstance representingList<String>:val nonNullStringType = String::class.starProjectedType val projection = KTypeProjection.invariant(nonNullStringType) val listOfStrings = listClass.createType(listOf(projection))Or, the following creates the type
List<String>?:val listOfStrings = listClass.createType(listOf(projection), nullable = true)
Both starProjectedType and createType are defined in package kotlin.reflect.full.
We're planning to introduce the possibility of getting a KType instance simply from a reified type parameter of an inline function which would help in some cases where the needed type is known statically, however currently it's not entirely clear if that's possible without major overhead. So, until that's implemented, please use the declarations explained above.
来源:https://stackoverflow.com/questions/44203297/kotlins-reflection-unknown-type-parameter