Bird
Raised Fist0
Kotlinprogramming~10 mins

Type constraints with upper bounds in Kotlin - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Type constraints with upper bounds
Define generic type T
↓
Set upper bound: T must be subtype of SomeClass
↓
Use T in function or class
↓
Call function with argument of type T or subtype
↓
Compile-time check: argument type fits upper bound?
Yes No↓
Run function
↓
Function logic uses T safely
↓
End
This flow shows how Kotlin checks that a generic type T respects an upper bound before running the function.
Execution Sample
Kotlin
fun <T : Number> doubleValue(value: T): Double {
    return value.toDouble() * 2
}

val result = doubleValue(10)
This function accepts any type T that is a subtype of Number and doubles its value.
Execution Table
StepActionType of TCheck Upper BoundResultOutput
1Call doubleValue with 10IntInt <: Number? YesPass
2Inside function: value.toDouble()IntN/AConvert 10 to 10.0
3Multiply 10.0 * 2DoubleN/AResult 20.0
4Return 20.0DoubleN/AFunction ends20.0
💡 Function ends after returning doubled value; type T confirmed as subtype of Number.
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3Final
valueN/A10 (Int)10 (Int)10 (Int)N/A
resultN/AN/AN/AN/A20.0 (Double)
Key Moments - 3 Insights
Why must the argument type be a subtype of Number?
Because the function declares <T : Number>, Kotlin enforces this at compile time (see execution_table step 1). Passing a type outside this bound causes a compile error.
What happens if we try to call doubleValue with a String?
The compiler rejects it immediately since String is not a subtype of Number, so the check in step 1 fails and the function does not run.
Why can we safely call toDouble() on value inside the function?
Because T is guaranteed to be a subtype of Number, which has the toDouble() method, so the call is safe (see step 2).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the type of T at step 1?
AString
BInt
CDouble
DAny
💡 Hint
Check the 'Type of T' column in execution_table row for step 1.
At which step does the function convert the value to Double?
AStep 2
BStep 1
CStep 3
DStep 4
💡 Hint
Look at the 'Action' and 'Result' columns in execution_table for step 2.
If we try to call doubleValue("text"), what happens?
AFunction runs and returns 0.0
BFunction runs but throws runtime error
CCompile error due to type constraint
DFunction runs and returns "texttext"
💡 Hint
Refer to key_moments about type constraint enforcement at compile time.
Concept Snapshot
fun <T : UpperBound> functionName(param: T) { ... }
- T must be subtype of UpperBound
- Compiler checks this before running
- Allows safe use of UpperBound methods on T
- Prevents passing incompatible types
- Enables flexible, type-safe generic code
Full Transcript
This visual trace shows how Kotlin uses type constraints with upper bounds in generics. The generic type T is declared with an upper bound Number, meaning T must be a subtype of Number. When calling the function doubleValue with an Int argument, Kotlin checks that Int is a subtype of Number and allows the call. Inside the function, it safely calls toDouble() on value because Number defines this method. The function doubles the value and returns a Double. If a type outside the bound, like String, is used, the compiler rejects the call. This ensures type safety and lets us write generic code that can use methods of the upper bound type.

Practice

(1/5)
1. What does the syntax <T : Number> mean in Kotlin generics?
easy
A. T must be a subtype of the Number class
B. T can be any type including Number
C. T must be a supertype of Number
D. T must be exactly the Number class

Solution

  1. Step 1: Understand the upper bound syntax

    The syntax <T : Number> means T is limited to types that inherit from Number.
  2. Step 2: Interpret subtype relationship

    This means T can be Number or any subclass like Int or Double, but not unrelated types.
  3. Final Answer:

    T must be a subtype of the Number class -> Option A
  4. Quick Check:

    Upper bound <T : Number> = subtype limit [OK]
Hint: Look for ': Type' to mean 'subtype of Type' [OK]
Common Mistakes:
  • Thinking T can be any type
  • Confusing subtype with supertype
  • Assuming exact type match only
2. Which of the following is the correct syntax to declare a generic function with an upper bound on type T to implement the Comparable interface?
easy
A. fun <T> max(a: T, b: T): T where T implements Comparable<T> { ... }
B. fun max(a: T, b: T): T { ... }
C. fun max(a: T, b: T): T { ... }
D. fun max(a: T, b: T): T { ... }

Solution

  1. Step 1: Recall Kotlin's upper bound syntax

    Kotlin uses <T : Interface> to specify T must implement that interface.
  2. Step 2: Identify correct syntax for Comparable

    The correct syntax is fun <T : Comparable<T>> .... Options B and D use Java syntax, and A uses a where clause but with incorrect syntax.
  3. Final Answer:

    fun <T : Comparable<T>> max(a: T, b: T): T { ... } -> Option B
  4. Quick Check:

    Kotlin upper bound uses ':' not 'implements' or 'extends' [OK]
Hint: Use ':' for upper bounds, not 'implements' or 'extends' [OK]
Common Mistakes:
  • Using Java syntax keywords like 'implements' or 'extends'
  • Confusing where clause syntax
  • Missing generic type parameter declaration
3. What will be the output of this Kotlin code?
fun <T : Number> printDouble(value: T) {
    println(value.toDouble() * 2)
}

fun main() {
    printDouble(5)
    printDouble(3.5)
}
medium
A. 5 and 3.5
B. Runtime error due to toDouble() call
C. Compilation error due to type mismatch
D. 10.0 and 7.0

Solution

  1. Step 1: Understand the generic constraint

    The function requires T to be a subtype of Number, so Int and Double are valid.
  2. Step 2: Calculate the output

    For 5 (Int), toDouble() is 5.0, multiplied by 2 is 10.0.
    For 3.5 (Double), toDouble() is 3.5, multiplied by 2 is 7.0.
  3. Final Answer:

    10.0 and 7.0 -> Option D
  4. Quick Check:

    Number constraint allows toDouble(), output matches calculations [OK]
Hint: Remember Number types have toDouble() method [OK]
Common Mistakes:
  • Expecting compilation error for Int argument
  • Confusing printed values with input values
  • Thinking toDouble() causes runtime error
4. Identify the error in this Kotlin code snippet:
fun <T : Comparable> compareValues(a: T, b: T): T {
    return if (a > b) a else b
}
medium
A. No error, code is correct
B. Cannot use '>' operator with Comparable
C. Missing generic type parameter in Comparable
D. Function must return Boolean, not T

Solution

  1. Step 1: Check Comparable usage

    Comparable is a generic interface and requires a type parameter, so it should be Comparable<T>.
  2. Step 2: Understand operator usage

    The '>' operator is not directly supported for Comparable, but Kotlin allows it if Comparable<T> is specified and operator overloading is present.
  3. Final Answer:

    Missing generic type parameter in Comparable -> Option C
  4. Quick Check:

    Comparable must be parameterized as Comparable<T> [OK]
Hint: Always specify type parameter for Comparable like Comparable<T> [OK]
Common Mistakes:
  • Omitting generic parameter in Comparable
  • Assuming '>' works without Comparable<T>
  • Confusing return type requirements
5. Given this Kotlin function:
fun <T : Number> sumList(numbers: List<T>): Double {
    return numbers.sumOf { it.toDouble() }
}

Which of these calls will cause a compilation error?
hard
A. sumList(listOf("1", "2", "3"))
B. sumList(listOf(1.5, 2.5, 3.5))
C. sumList(listOf(1, 2, 3))
D. sumList(listOf(1L, 2L, 3L))

Solution

  1. Step 1: Analyze the function's type constraint

    The function requires a List of elements where each element is a subtype of Number.
  2. Step 2: Check each call's argument type

    Options B, C, and D pass lists of Double, Int, and Long respectively.
    sumList(listOf("1", "2", "3")) passes a list of Strings, which are not subtypes of Number, causing a compilation error.
  3. Final Answer:

    sumList(listOf("1", "2", "3")) -> Option A
  4. Quick Check:

    Only Number subtypes allowed, String list fails [OK]
Hint: Only Number subtypes allowed in sumList argument [OK]
Common Mistakes:
  • Passing String list instead of Number list
  • Assuming any list works
  • Ignoring generic type constraints
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard