Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Generic constraints in Kotlin restrict the set of types that can be substituted for a given type parameter. By defining an upper bound, the compiler enforces that any type argument passed to the generic class, interface, or function must be a subtype of that specified bound.

Single Upper Bound

The standard mechanism for applying a constraint is declaring a single upper bound using a colon : after the type parameter identifier.
class Container<T : Number>(val value: T)

fun <T : Comparable<T>> sort(list: List<T>) { /* ... */ }
If no upper bound is explicitly declared, Kotlin assigns an implicit default upper bound of Any?. This means an unconstrained type parameter accepts any nullable or non-nullable type.

Multiple Upper Bounds

When a type parameter must satisfy more than one constraint, Kotlin requires the where clause. The where clause is appended after the primary declaration signature but before the construct’s body.
class Processor<T> where T : CharSequence, T : Appendable {
    // T is constrained to types that implement both CharSequence and Appendable
}

fun <T> processItems(items: List<T>) where T : Runnable, T : Cloneable {
    // ...
}
Architectural Rules for Multiple Bounds:
  • A type parameter can have a maximum of one concrete or abstract class in its upper bounds.
  • All other bounds specified in the where clause for that type parameter must be interfaces.
  • The Kotlin compiler does not enforce any specific order between class and interface bounds within the where clause.

Nullability Constraints

Because the implicit default bound is Any?, type parameters accept null values by default. To strictly enforce a non-nullable type argument without restricting it to a specific class hierarchy, the upper bound must be explicitly set to Any.
// T accepts nullable types (e.g., String?)
class DefaultContainer<T> 

// T strictly requires non-nullable types (e.g., String)
class NonNullContainer<T : Any>

Type Parameter as an Upper Bound

A type parameter can be constrained by another type parameter declared within the same signature. This enforces a strict subtyping relationship between the two generic arguments at compile time.
fun <T, U : T> copyData(source: List<U>, destination: MutableList<T>) {
    // The compiler guarantees U is a subtype of T
}
Master Kotlin with Deep Grasping Methodology!Learn More