ProgramGuru

Generics and type constraints

Generics and type constraints

A library helper should return the first item whether it receives names or marks. Generics describe an algorithm in terms of a placeholder type while preserving the actual type used at each call. This avoids treating every value as untyped Any.

What you’ll learn

  • Preserve types through a generic function.
  • Require capabilities before using an operation.

Generics and type constraints in the example

  1. Placeholder type

    A library helper should return the first item whether it receives names or marks.

    Placeholder type
  2. Concrete call type

    A type parameter such as T preserves the relationship between inputs and outputs.

    Concrete call type
  3. Type-preserving result

    The calls preserve Int and String element types, while empty input returns null.

    Type-preserving result
The calls preserve Int and String element types, while empty input returns null. The generic operation needs only the list API, so no numeric or comparison assumption is required.

Understand generics and type constraints

A type parameter such as T preserves the relationship between inputs and outputs. Add a bound when the algorithm requires operations such as comparison. Kotlin declaration-site out and in describe supported variance, but the allowed operations still follow their type-position rules.

Follow generics and type constraints

Save the complete source as Main.kt and use the Kotlin/JVM environment. No separate input file is needed.

Kotlin/JVM · complete program

fun <T> firstItem(items: List<T>): T? = items.firstOrNull()
fun main() {
  println(firstItem(listOf(80, 90)))
  println(firstItem(listOf("Diya", "Saira")))
  println(firstItem(emptyList<Int>()))
}

Expected output

80
Diya
null

Follow the execution

The calls preserve Int and String element types, while empty input returns null. The generic operation needs only the list API, so no numeric or comparison assumption is required.

Try this in the Kotlin compiler by pasting the complete program.

Practice: Generics and type constraints

Your task: Can an unconstrained T always be added with +?

Kotlin/JVM · complete program

fun <T> firstItem(items: List<T>): T? = items.firstOrNull()
fun main() {
  println(firstItem(listOf(80, 90)))
  println(firstItem(listOf("Diya", "Saira")))
  println(firstItem(emptyList<Int>()))
}

Worked answer

No. Its contract does not promise that operation. Require an appropriate capability or accept a supplied combining function.

Generics and type constraints: the important boundary

JVM generic types have erasure-related runtime limitations. Reified type parameters in suitable inline functions allow some runtime type operations, but do not make every generic type check or nested argument fully available.

Check your understanding

Can an unconstrained T always be added with +?
Choose one answer. You can try again.

Answer and explanation

No.

No. Its contract does not promise that operation. Require an appropriate capability or accept a supplied combining function.

Generics and type constraints: what to keep in mind

No. Its contract does not promise that operation. Require an appropriate capability or accept a supplied combining function. JVM generic types have erasure-related runtime limitations.

Further reading: official Kotlin documentation for this topic.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Visibility and encapsulation →