mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
3.0 KiB
3.0 KiB
Reified Type Parameters
Goal: support run-time access to types passed to functions, as if they were reified (currently limited to inline functions only).
Syntax
A type parameter of a function can be marked as reified:
inline fun <reified T> foo() {}
Semantics, Checks and Restrictions
Definition A well-formed type is called runtime-available if
- it has the form
C, whereCis a classifier (object, class or trait) that has either no type parameters, or all its type parameters arereified, with the exception for classNothing, - it has the form
G<A1, ..., An>, whereGis a classifier withntype parameters, and for every type parameterTiat least one of the following conditions hold:Tiis areifiedtype parameter and the corresponding type argumentAiis a runtime-available type,Aiis a star-projection (e.g. forList<*>,A1is a star-projection);
- it has the form
T, andTis areifiedtype parameter.
Examples:
- Runtime-available types:
String,Array<String>,List<*>; - Non-runtime-available types:
Nothing,List<String>,List<T>(for anyT) - Conditional:
Tis runtime-available iff the type parameterTisreified, same forArray<T>
Only runtime-available types are allowed as
- right-hand arguments for
is,!is,as,as? - arguments for
reifiedtype parameters of calls (for types any arguments are allowed, i.e.Array<List<String>>is still a valid type).
As a consequence, if T is a reified type parameter, the following constructs are allowed:
x is T,x !is Tx as T,x as? T- reflection access on
T:javaClass<T>(),T::class(when supported)
Restrictions regarding reified type parameters:
- Only a type parameter of an
inlinefunction can be markedreified - The built-in class
Arrayis the only class whose type parameter is markedreified. Other classes are not allowed to declarereifiedtype parameters. - Only a runtime-available type can be passed as an argument to a
reifiedtype parameter
Notes:
- No warning is issued on
inlinefunctions declaring no inlinable parameters of function types, but having areifiedtype parameter declared.
Implementation notes for the JVM
In inline functions, occurrences of a reified type parameter T are replaced with the actual type argument.
If actual type argument is a primitive type, it's wrapper will be used within reified bytecode.
open class TypeLiteral<T> {
val type: Type
get() = (javaClass.getGenericSuperclass() as ParameterizedType).getActualTypeArguments()[0]
}
inline fun <reified T> typeLiteral(): TypeLiteral<T> = object : TypeLiteral<T>() {} // here T is replaced with the actual type
typeLiteral<String>().type // returns 'class java.lang.String'
typeLiteral<Int>().type // returns 'class java.lang.Integer'
typeLiteral<Array<String>>().type // returns '[Ljava.lang.String;'
typeLiteral<List<*>>().type // returns 'java.util.List<?>'