Generics let functions, classes, and interfaces describe types with placeholders, then replace those placeholders with concrete type arguments. A List<String> records what its elements are; a Map<String, Person> records both key and value types. Kotlin requires those arguments to be explicit or inferred, unlike Java raw types. section 11.1
Write a generic function
Place type parameters before the function name. Here T connects the collection element type to the code that processes each element: fun <T> joinToString( collection: Collection<T>, separator: String, prefix: String, postfix: String ): String { /* append each element */ } The same declaration works for collections of any element type. At a call site, Kotlin normally infers T from the argument, so explicit type arguments are rarely needed. section 3.2 section 11.1.1
A type parameter can appear in a receiver, parameter, return type, lambda type, or generic extension property. In `fun <T> List<T>.filter(predicate: (T) -> Boolean): List<T>`, the receiver establishes T and the lambda parameter becomes that same type. Classes use the same angle-bracket syntax: `class ArrayList<T> : List<T>`. section 11.1.1 section 11.1.2
Let inference carry the type
A nonempty factory call supplies enough evidence for inference: val authors = listOf("Sveta", "Seb", "Dima") // List<String> An empty collection needs a type from somewhere: val readers: MutableList<String> = mutableListOf() // or: val readers = mutableListOf<String>() section 11.1
Unbounded Kotlin type parameters accept nullable type arguments: an unbounded T effectively has upper bound `Any?`. Use `T : Any` when callers must supply a non-null type; the compiler then rejects arguments such as `String?` and values such as `null`. section 11.1.4 section 7.11
Type arguments guide compile-time checking but are erased at run time. Code can test `is List<*>`, but normally cannot distinguish `List<String>` from `List<Int>` with an `is` check. Inline reified type parameters are the stated exception for runtime type use. section 11.2.1 section 11.4
Generics also define how related parameterized types interact. `out` makes a producer covariant, allowing `List<String>` where `List<Any>` is expected; `in` makes a consumer contravariant. For individual uses, `out` and `in` projections express read-only or write-only roles, paralleling Java wildcards. section 11.3.3 section 11.3.5
Listing 11.2 Calling a generic higher-order function
fun main() {
val authors = listOf("Sveta", "Seb", "Roman", "Dima")
val readers = mutableListOf<String>("Seb", "Hadi")
println(readers.filter { it !in authors })
// [Hadi]
}
Inspect how `filter` infers `T` as `String` from a `List<String>` receiver and gives the lambda parameter that type. section 11.1.1



















