← 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'.
Syntax
kotlin
fun functionName(value: Any) {
    if (value is List<*>) {     // any element type
        // can read elements as Any?
    }
}

fun read(items: List<*>) { }

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
// Define the function `printSize` taking `value`
fun printSize(value: Any) {
    // Check whether `value is List<*>`
    if (value is List<*>) {
        // Print "List size: ${value.size}" to the console, with a trailing newline
        println("List size: ${value.size}")
    }
}

// Entry point: execution of the program starts here
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
// Define the function `printAll` taking `items`
fun printAll(items: List<*>) {
    // Loop over `items`, binding each item to `item`
    for (item in items) {
        // Print `item` to the console, with a trailing newline
        println(item)
    }
}

// Entry point: execution of the program starts here
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
// Define the function `sumConcrete` taking `numbers` and returning an Int
fun sumConcrete(numbers: List<Int>): Int = numbers.sum()

// Entry point: execution of the program starts here
fun main() {
    // Print `sumConcrete(listOf(1, 2, 3, 4))` to the console, with a trailing newline
    println(sumConcrete(listOf(1, 2, 3, 4)))
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
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.