← Back to Kotlin Course | Chapter 11: Generics | Lesson 6 of 6

Star Projection

A star projection is Kotlin's way of saying 'I don't care what specific type this generic is holding, I just want to work with it generically'.

Using Star Projection in Type Checks

Because generic type arguments are erased at runtime, checking whether something is a List of unknown element type uses the star projection syntax List<*>.

Example: Using Star Projection in Type Checks

markup
fun printSize(value: Any) {
    if (value is List<*>) {
        println("List size: ${value.size}")
    }
}

fun main() {
    printSize(listOf(1, 2, 3))
    printSize(listOf("a", "b"))
}

Reading from a Star-Projected Type

A star-projected generic type still allows reading elements out safely, since any element can always be treated as Any? regardless of its real type.

Example: Reading from a Star-Projected Type

markup
fun printAll(items: List<*>) {
    for (item in items) {
        println(item)
    }
}

fun main() {
    printAll(listOf(1, "two", 3.0))
}

Why Writing Is Disallowed

You cannot add elements to a star-projected MutableList<*> because the compiler has no way to guarantee that whatever you try to insert matches the list's real, unknown element type.

Example: Why Writing Is Disallowed

markup
fun describeMutable(list: MutableList<*>) {
    // list.add("something") would not compile here
    println("A mutable list with ${list.size} elements of an unknown type")
}

fun main() {
    val numbers = mutableListOf(1, 2, 3)
    describeMutable(numbers)
}

Star Projection vs a Concrete Type

Whenever the actual element type is known and relevant, prefer a concrete generic type like List<String> over List<*>, since it lets the compiler check far more of your code for correctness.

Example: Star Projection vs a Concrete Type

markup
fun sumConcrete(numbers: List<Int>): Int = numbers.sum()

fun main() {
    println(sumConcrete(listOf(1, 2, 3, 4)))
}
Common Mistakes
  1. Trying to add an element to a MutableList<*>, which the compiler rejects since the actual element type is unknown, so nothing can be safely inserted.
  2. Confusing List<*> with List<Any?>; a star projection is more restrictive because it also blocks unsafe writes, while List<Any?> allows adding any value.
  3. Overusing star projection when the actual type parameter is already known and a concrete generic type would be clearer and safer.
Chapter Summary
  • Type<*> (a star projection) represents a generic type when the exact type argument is unknown or unimportant.
  • A star-projected generic type allows safe reading (of a supertype like Any?) but disallows writing, since the compiler cannot verify type safety for insertion.
  • Star projection is commonly used in is checks, like is List<*>, since erasure prevents checking the actual element type.
  • List<*> behaves like a read-only list of unknown element type, distinct from List<Any?> which explicitly allows any type.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.