> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Kotlin Star Projection

Star projection (`*`) is a type projection syntax in Kotlin used to represent an unknown type argument within a generic type. It acts as a type-safe equivalent to Java's unbounded wildcards (`<?>`), allowing developers to reference a generic type without specifying its exact type parameter, while the compiler strictly enforces type safety based on the parameter's declaration-site variance.

When a generic type is instantiated with a star projection, the Kotlin compiler automatically resolves the allowed read and write operations by mapping the `*` to specific `in` (contravariant) and `out` (covariant) projections.

## Runtime Type Checking and Type Erasure

A fundamental application of star projections is performing runtime type checks. Because Kotlin erases generic type arguments at runtime (type erasure), it is impossible to check if an object is an instance of a generic type with a specific type argument. Attempting to do so results in a compiler error. Star projections provide the required mechanism to safely check the base type at runtime.

```kotlin theme={"dark"}
fun checkType(obj: Any) {
    // if (obj is List<String>) { ... } // Compilation error: Cannot check for instance of erased type
    
    if (obj is List<*>) {
        // Allowed: Checks if obj is a List of some unknown type
        println("Object is a List of size ${obj.size}")
    }
}
```

## Variance Resolution Rules

The behavior of a star-projected type depends entirely on how the generic type parameter was originally declared.

### 1. Covariant Declaration (`out T`)

If a type parameter is declared as covariant, the star projection allows reading the upper bound of `T`, but prohibits writing.

* **Declaration:** `interface Producer<out T>`
* **Star Projection:** `Producer<*>`
* **Compiler Interpretation:** `Producer<out Any?>`
* **Behavior:** You can safely read values of type `Any?` from the object, but you cannot pass any values to methods that expect `T`.

```kotlin theme={"dark"}
interface Producer<out T> {
    fun produce(): T
}

fun testProducer(producer: Producer<*>) {
    val item: Any? = producer.produce() // Allowed: Reads as Any?
}
```

### 2. Contravariant Declaration (`in T`)

If a type parameter is declared as contravariant, the star projection prevents writing any value to the object, as the exact accepted type is unknown.

* **Declaration:** `interface Consumer<in T>`
* **Star Projection:** `Consumer<*>`
* **Compiler Interpretation:** `Consumer<in Nothing>`
* **Behavior:** You cannot safely write *any* value to methods expecting `T` (because the `Nothing` type has no instances).

```kotlin theme={"dark"}
interface Consumer<in T> {
    fun consume(item: T)
}

fun testConsumer(consumer: Consumer<*>) {
    // consumer.consume("test") // Compilation error: Expected Nothing
}
```

### 3. Invariant Declaration (`T`)

If a type parameter is invariant (neither `in` nor `out`), the star projection splits the behavior for reading and writing.

* **Declaration:** `interface MutableBox<T>`
* **Star Projection:** `MutableBox<*>`
* **Compiler Interpretation:** `MutableBox<out Any?>` for reading, `MutableBox<in Nothing>` for writing.
* **Behavior:** You can read values as `Any?`, but you cannot write any values.

```kotlin theme={"dark"}
interface MutableBox<T> {
    fun get(): T
    fun set(value: T)
}

fun testBox(box: MutableBox<*>) {
    val item: Any? = box.get() // Allowed: Reads as Any?
    // box.set("test") // Compilation error: Expected Nothing
}
```

### 4. Type Parameters with Upper Bounds

If the generic type parameter has a defined upper bound other than `Any?`, the star projection respects that bound during covariant reads.

* **Declaration:** `interface BoundBox<T : CharSequence>`
* **Star Projection:** `BoundBox<*>`
* **Compiler Interpretation:** `BoundBox<out CharSequence>` for reading, `BoundBox<in Nothing>` for writing.

```kotlin theme={"dark"}
interface BoundBox<T : CharSequence> {
    fun get(): T
}

fun testBoundBox(boundBox: BoundBox<*>) {
    val item: CharSequence = boundBox.get() // Allowed: Reads as CharSequence
}
```

## Multiple Type Parameters

For types with multiple generic parameters, each parameter can be star-projected independently. The compiler resolves each `*` according to its specific declaration.

```kotlin theme={"dark"}
interface Function<in T, out U> {
    fun apply(arg: T): U
}

fun testFunctions(
    f1: Function<*, String>, // Resolves to Function<in Nothing, String>
    f2: Function<Int, *>,    // Resolves to Function<Int, out Any?>
    f3: Function<*, *>       // Resolves to Function<in Nothing, out Any?>
) {
    // Implementation omitted
}
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Kotlin Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
