Reified type parameters are type parameters that retain more characteristics of actual types than normal type parameters do.
For a gentle introduction to the topic, check out the guide, Getting Real with Reified Type Parameters.
Examples
Single Parameter
inline fun <reified T> Any.isInstanceOf(): Boolean = this is T
Here we created an extension function to wrap the more common is
operator. Why is this example so magical? Because normally, compiling this is T
would result in an error since the type of T
is erased.
To invoke the function above, we can do something like this:
val isStringAString = "String".isInstanceOf<String>()
val isIntAString = 1.isInstanceOf<String>()
Multiple Parameters
You can specify multiple parameters as reified
:
inline fun <reified T, reified U> haveSameType(first: T, second: U) =
first is U && second is T
You can specify that some type parameters are reified and others are not:
inline fun <reified T, U> listOfTypeOrNull(obj: U): List<T>? =
if (obj is T) listOf(obj) else null
Extension Properties
You can also technically create an extension property that uses a reified type parameter, but it requires that the type parameter is used as the receiver type:
inline val <reified T> T.clazz
get() = T::class.java
I haven’t been able to come up with a good use case for this, because you’ve got an actual object (this
) that lets you do even more than you could do with a reified type parameter. For example, the same property could be implemented like this:
val <T : Any> T.clazz
get() = this.javaClass
Characteristics
To specify a reified type parameter:
- The keyword
reified
goes before the name in the type parameter declaration. - The function must be declared
inline
.
This second requirement also restricts where the function can go. For example, a local function (that is, a function defined inside another function) can’t be inlined.
Alternatives
Some of the main benefits of reified type parameters are:
- You can do type checks with
is
- You can do casts without unchecked cast warnings
- You can assign class objects by appending
::class.java
to the parameter name. e.g.,val x = T::class.java
There are klunky workarounds that Java developers have adopted over the years to accomplish these things, involving things like reflection, or passing Class<T>
objects as arguments to functions. Because reified type parameters are a more concise solution - especially when types can be inferred - they’re preferrable in most cases.
Since functions with reified type parameters must be declared inline
, one disadvantage is that you’d want to keep your function small, or else your compiled code will get bloated quickly. On the other hand, writing small, focused functions is usually considered a good practice anyway.
For more info about reified type parameters, take a look at the guide, Getting Real with Reified Type Parameters.