Kotlin Reified Types
A reified type parameter keeps its type argument at run time inside an inline function. The function can then test values against that type with the is operator.
ofType built on the is test
The inline function walks the list and keeps each item that passes the is T test. The same function serves strings and ints.
inline fun <reified T> List<Any?>.ofType(): List<T> {
val result = mutableListOf<T>()
for (item in this) {
if (item is T) result.add(item)
}
return result
}
fun main() {
val mixed = listOf(2, "two", 7, "four")
println(mixed.ofType<String>())
println(mixed.ofType<Int>().sum())
}filterIsInstance does the same job
filterIsInstance is the standard library workhorse for this shape. It returns a new list holding only the values of the named type.
fun main() {
val mixed = listOf<Any>("a", 1, "b", 2.5, "c")
println(mixed.filterIsInstance<String>())
println(mixed.filterIsInstance<Number>())
}Counting one type in a mixed list
A second inline function counts the items that pass the is T test. The count changes with the type named at each call.
inline fun <reified T> List<Any?>.countOfType(): Int {
var total = 0
for (item in this) {
if (item is T) total++
}
return total
}
fun main() {
val mixed = listOf("x", 4, "y", 8, "z", 15)
println(mixed.countOfType<String>())
println(mixed.countOfType<Int>())
}Reified without inline fails
This program declares a reified type parameter on a plain function. The compiler rejects the declaration itself.
fun <reified T> firstOf(items: List<Any?>): T? {
for (item in items) {
if (item is T) return item
}
return null
}
fun main() {
println(firstOf<String>(listOf(1, "two")))
}Example
inline fun <reified T> List<Any?>.ofType(): List<T> {
val result = mutableListOf<T>()
for (item in this) {
if (item is T) result.add(item)
}
return result
}
fun main() {
val crate = listOf<Any>("rope", 12, "lamp", 30, "map", 7)
val labels = crate.ofType<String>()
val weights = crate.ofType<Int>()
println(labels)
println(weights.sum())
println(crate.filterIsInstance<String>().size)
}Key points
- Only an inline function can declare a reified type parameter.
- Inside the function, the is operator can test a value against the reified type.
- A value that passes the test can be used as that type.
- The standard library function filterIsInstance is built on a reified type parameter.
- Callers write the wanted type in angle brackets at the call site.
In this example, one mixed list holds labels and weights. ofType pulls the strings into one list and the ints into another. The weights sum to 49, and filterIsInstance confirms the crate holds three strings.
Note
A plain function cannot declare a reified type parameter, and the compiler rejects it.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Kotlin Playground
Exercise
Why can ofType test values with the is T check?