Bird
Raised Fist0
Kotlinprogramming~15 mins

Star projection for unknown types in Kotlin - Deep Dive

Choose your learning style10 modes available
Overview - Star projection for unknown types
What is it?
Star projection in Kotlin is a way to handle generic types when you don't know or don't care about the specific type argument. It uses a special symbol '*' to represent an unknown type safely. This lets you work with generic classes or interfaces without specifying exact types, avoiding type errors. It helps keep your code flexible and safe when dealing with generics.
Why it matters
Without star projections, you would have to know the exact type parameters to use generic classes, which is often impossible or inconvenient. This would make your code less reusable and more error-prone. Star projections solve this by allowing you to say, "I don't know the type, but I want to use this generic safely." This makes Kotlin programs more robust and easier to maintain when working with generics.
Where it fits
Before learning star projections, you should understand Kotlin generics and variance (in/out keywords). After mastering star projections, you can explore advanced generic topics like type projections, reified types, and generic constraints.
Mental Model
Core Idea
Star projection means using '*' as a placeholder for an unknown generic type to safely interact with generic classes without specifying exact types.
Think of it like...
Imagine a box labeled 'something inside' without knowing what exactly is inside. You can still carry or move the box safely without opening it or knowing its contents.
GenericClass<*>  
  │  
  ├─ Represents GenericClass with unknown type
  ├─ Safe to read as 'Any?' or write nothing
  └─ Prevents unsafe operations on unknown types
Build-Up - 7 Steps
1
FoundationUnderstanding Kotlin Generics Basics
🤔
Concept: Learn what generics are and why Kotlin uses them.
Generics let you write classes and functions that work with any type. For example, List can hold any type T. This avoids writing many similar classes for different types.
Result
You can create a List or List from the same List class.
Understanding generics is essential because star projections only make sense when you know what generics do.
2
FoundationVariance: In and Out Keywords
🤔
Concept: Learn how Kotlin controls subtype relationships with 'in' and 'out'.
The 'out' keyword means a generic type is only produced (read), like List. The 'in' keyword means it is only consumed (written), like Comparable. This controls how types relate to each other safely.
Result
You can safely assign List to List but not vice versa.
Variance rules help prevent type errors and are the foundation for understanding star projections.
3
IntermediateWhat is Star Projection in Kotlin?
🤔Before reading on: do you think star projection allows writing to generic types or only reading? Commit to your answer.
Concept: Star projection uses '*' to represent an unknown generic type safely, allowing limited operations.
When you write List<*>, it means a list of some unknown type. You can read elements as 'Any?' but cannot add elements because the type is unknown. This protects type safety.
Result
You can use List<*> to accept any list without knowing its element type, but you cannot add elements to it.
Knowing that star projection restricts writing but allows safe reading prevents common type errors.
4
IntermediateHow Star Projection Relates to Variance
🤔Before reading on: do you think star projection is equivalent to 'out Any?' or something else? Commit to your answer.
Concept: Star projection behaves like a mix of 'out' and 'in' depending on the generic declaration.
For a generic type T declared as 'out T', star projection means 'out Any?'. For 'in T', it means 'in Nothing'. For invariant T, it means 'out Any?' for reading and 'in Nothing' for writing. This ensures safe usage.
Result
Star projection adapts to variance to keep operations safe without knowing the exact type.
Understanding this helps you predict what operations are allowed on star-projected types.
5
IntermediateUsing Star Projection in Function Parameters
🤔
Concept: Learn how star projections help when you accept generic types but don't care about their exact type.
Suppose you write a function that accepts List<*>. You can iterate over elements as Any? but cannot add elements. This lets you write flexible APIs that accept any generic list safely.
Result
Your function can handle lists of any type without risking type errors.
Knowing how to use star projections in parameters increases your code's flexibility and safety.
6
AdvancedStar Projection and Type Safety Guarantees
🤔Before reading on: do you think star projection can cause runtime type errors? Commit to your answer.
Concept: Star projection enforces compile-time restrictions to prevent unsafe operations on unknown types.
Because the compiler treats star-projected types as unknown, it forbids adding elements or unsafe casts. This prevents runtime ClassCastException related to generics.
Result
Your program avoids common generic type errors at runtime thanks to star projection restrictions.
Understanding how star projection enforces safety at compile time helps you trust Kotlin's type system.
7
ExpertStar Projection Internals and Compiler Behavior
🤔Before reading on: do you think star projection is just syntax sugar or involves deeper compiler logic? Commit to your answer.
Concept: Star projection is implemented by the Kotlin compiler as a special kind of type projection with specific bounds depending on variance.
The compiler replaces '*' with appropriate projections: 'out Any?' or 'in Nothing' depending on the generic declaration. This affects bytecode and type checking. It is not just syntax but a core part of Kotlin's type system.
Result
You understand that star projection is a powerful compiler feature ensuring safe generic usage.
Knowing the compiler's role clarifies why star projection is safe and how it integrates with Kotlin's type system.
Under the Hood
Star projection is a compiler-level feature where the '*' symbol is translated into a type projection with specific upper or lower bounds depending on the generic parameter's variance. For 'out' parameters, it becomes 'out Any?', allowing safe reading. For 'in' parameters, it becomes 'in Nothing', preventing writing. For invariant parameters, it combines these rules to restrict unsafe operations. This ensures type safety without knowing the exact type argument.
Why designed this way?
Kotlin needed a way to handle generic types when the exact type argument is unknown or irrelevant, without sacrificing type safety. Alternatives like raw types (from Java) are unsafe and error-prone. Star projection provides a safe, expressive, and compiler-enforced way to work with unknown generics, improving code robustness and interoperability.
GenericClass<T>  
     │          
     ├─ Variance: in/out/invariant
     │          
     ├─ Star Projection '*' translates to:
     │     ├─ out T => out Any?
     │     ├─ in T => in Nothing
     │     └─ invariant T => out Any? & in Nothing
     │          
     └─ Compiler enforces safe operations based on these bounds
Myth Busters - 4 Common Misconceptions
Quick: Does List<*> allow adding any element safely? Commit yes or no.
Common Belief:List<*> means you can add any type of element because the type is unknown.
Tap to reveal reality
Reality:You cannot add any element to List<*> because the element type is unknown and adding could break type safety.
Why it matters:Trying to add elements to star-projected collections causes compile errors or unsafe casts, leading to bugs or crashes.
Quick: Is star projection the same as using 'Any' as the generic type? Commit yes or no.
Common Belief:Using List<*> is the same as List because both accept any type.
Tap to reveal reality
Reality:List<*> is not the same as List. List allows adding any element, but List<*> restricts adding to maintain safety.
Why it matters:Confusing these leads to incorrect assumptions about what operations are allowed, causing type errors.
Quick: Does star projection remove all type information? Commit yes or no.
Common Belief:Star projection completely erases the generic type information at runtime.
Tap to reveal reality
Reality:Star projection preserves variance and type bounds at compile time; it does not erase all type information but restricts usage safely.
Why it matters:Misunderstanding this can cause misuse of star projections and unexpected runtime behavior.
Quick: Can star projection be used only with classes, or also with functions? Commit your answer.
Common Belief:Star projection applies only to generic classes and cannot be used in function signatures.
Tap to reveal reality
Reality:Star projection can be used in function parameters and return types to handle unknown generic types safely.
Why it matters:Not knowing this limits the flexibility of API design and generic programming.
Expert Zone
1
Star projection adapts differently depending on whether the generic parameter is declared with 'in', 'out', or invariant, affecting what operations are allowed.
2
Using star projections can sometimes hide type errors that would be caught with explicit types, so careful API design is needed.
3
Star projections interact subtly with Kotlin's nullability system, often treating unknown types as nullable Any? to maintain safety.
When NOT to use
Avoid star projections when you need to perform specific operations on generic types, such as adding elements or calling type-specific methods. Instead, use explicit generic parameters or bounded type parameters to maintain type safety and clarity.
Production Patterns
In production, star projections are commonly used in library APIs to accept generic types flexibly, such as accepting List<*> to process any list without modifying it. They are also used in Kotlin's standard library for interoperability with Java raw types and to simplify generic code where exact types are irrelevant.
Connections
Type Erasure in Java
Star projection addresses some problems caused by Java's type erasure by providing safer generic handling at compile time.
Understanding star projection helps grasp how Kotlin improves on Java generics by enforcing safety despite type erasure.
Covariance and Contravariance in Type Theory
Star projection relies on variance concepts from type theory to safely handle unknown types.
Knowing variance theory deepens understanding of why star projection restricts operations the way it does.
Black Box Abstraction in Software Engineering
Star projection acts like a black box abstraction, hiding internal type details while allowing safe interaction.
Recognizing star projection as a form of abstraction clarifies its role in managing complexity and safety.
Common Pitfalls
#1Trying to add elements to a star-projected collection.
Wrong approach:val list: MutableList<*> = mutableListOf() list.add("Hello") // Error: Out-projected type prohibits the use of 'add'
Correct approach:val list: MutableList = mutableListOf() as MutableList list.add("Hello") // Allowed because type is explicit
Root cause:Misunderstanding that star projection restricts writing to prevent unsafe operations.
#2Confusing List<*> with List and assuming they behave the same.
Wrong approach:fun process(list: List<*>) { list.forEach { println(it.length) } // Error: 'Any?' has no 'length' }
Correct approach:fun process(list: List) { list.forEach { println((it as String).length) } // Safe if list contains Strings }
Root cause:Assuming star projection preserves element type methods without casting.
#3Using star projection when specific type operations are needed.
Wrong approach:fun addString(list: MutableList<*>) { list.add("text") // Error }
Correct approach:fun addString(list: MutableList) { list.add("text") // Correct }
Root cause:Using star projection too broadly without considering operation requirements.
Key Takeaways
Star projection uses '*' to represent an unknown generic type safely in Kotlin.
It restricts certain operations like adding elements to maintain type safety.
Star projection adapts to variance annotations to allow safe reading or writing.
It is a compiler feature that prevents common generic type errors at compile time.
Using star projections wisely increases code flexibility without sacrificing safety.

Practice

(1/5)
1. What does the star projection * represent in Kotlin generics?
easy
A. A type that can only be used with primitive data types
B. A specific generic type that must be defined explicitly
C. A wildcard that allows writing but restricts reading
D. An unknown generic type that allows safe reading but restricts writing

Solution

  1. Step 1: Understand star projection meaning

    The star projection * means an unknown generic type in Kotlin.
  2. Step 2: Analyze its usage

    It allows safe reading from generic collections but restricts writing to avoid type errors.
  3. Final Answer:

    An unknown generic type that allows safe reading but restricts writing -> Option D
  4. Quick Check:

    Star projection = unknown generic type with safe read [OK]
Hint: Star projection means unknown type, safe read only [OK]
Common Mistakes:
  • Thinking star projection allows writing to generics
  • Confusing star projection with specific generic types
  • Assuming star projection only works with primitives
2. Which of the following is the correct syntax to declare a list with star projection in Kotlin?
easy
A. val list: List<Any> = listOf(1, 2, 3)
B. val list: List<*> = listOf(1, 2, 3)
C. val list: List<> = listOf(1, 2, 3)
D. val list: List = listOf(1, 2, 3)

Solution

  1. Step 1: Recall star projection syntax

    Star projection uses * inside angle brackets to represent unknown type.
  2. Step 2: Check each option

    val list: List<*> = listOf(1, 2, 3) uses List<*> which is correct syntax for star projection.
  3. Final Answer:

    val list: List<*> = listOf(1, 2, 3) -> Option B
  4. Quick Check:

    Star projection syntax = List<*> [OK]
Hint: Star projection syntax always uses * inside angle brackets [OK]
Common Mistakes:
  • Leaving angle brackets empty like List<>
  • Using List<Any> which is not star projection
  • Confusing star projection with out-projection
3. What will be the output of the following Kotlin code?
fun printFirst(list: List<*>) {
    println(list[0])
}

fun main() {
    val numbers: List<Int> = listOf(10, 20, 30)
    printFirst(numbers)
}
medium
A. 10
B. Compilation error
C. null
D. Runtime exception

Solution

  1. Step 1: Understand star projection usage in function

    The function accepts List<*>, meaning unknown generic type, safe to read elements.
  2. Step 2: Analyze the call with List<Int>

    Passing List<Int> is valid; reading list[0] returns 10 safely.
  3. Final Answer:

    10 -> Option A
  4. Quick Check:

    Reading from List<*> returns element safely [OK]
Hint: Reading from List<*> works, writing does not [OK]
Common Mistakes:
  • Assuming star projection causes compile error
  • Expecting null instead of actual element
  • Thinking runtime exception occurs on read
4. Identify the error in the following Kotlin code using star projection:
fun addElement(list: MutableList<*>, element: Any) {
    list.add(element)
}
medium
A. Element type Any is incompatible with list
B. Syntax error in function declaration
C. Cannot add element to MutableList<*> due to unknown type
D. No error, code compiles and runs fine

Solution

  1. Step 1: Understand star projection with MutableList

    MutableList<*> means unknown generic type; writing is restricted to avoid type errors.
  2. Step 2: Analyze the add operation

    Trying to add element causes compile error because type is unknown and unsafe to write.
  3. Final Answer:

    Cannot add element to MutableList<*> due to unknown type -> Option C
  4. Quick Check:

    Writing to MutableList<*> causes error [OK]
Hint: Cannot write to star-projected mutable collections [OK]
Common Mistakes:
  • Thinking add works with MutableList<*>
  • Confusing syntax error with type error
  • Assuming Any type is always accepted
5. Given a function that accepts a list with star projection, how can you safely copy elements from List<*> to a MutableList<Any> in Kotlin?
hard
A. Use a loop to cast each element to Any and add to MutableList<Any>
B. Directly assign List<*> to MutableList<Any>
C. Use star projection on both lists
D. Use MutableList<*> instead of MutableList<Any>

Solution

  1. Step 1: Understand star projection restrictions

    List<*> allows safe reading but elements are of unknown type, so direct assignment to MutableList<Any> is unsafe.
  2. Step 2: Safely copy elements

    Use a loop to read each element and cast to Any before adding to MutableList<Any>, ensuring type safety.
  3. Final Answer:

    Use a loop to cast each element to Any and add to MutableList<Any> -> Option A
  4. Quick Check:

    Copy with loop and cast = safe transfer [OK]
Hint: Copy elements with loop and cast from List<*> to MutableList<Any> [OK]
Common Mistakes:
  • Trying direct assignment between incompatible generic types
  • Using star projection on mutable list incorrectly
  • Ignoring type casting when copying elements
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