Reified type parameters cannot do everything. Name concrete limitations of `reified` and explain how you work around them (e.g., needing a real `T` instance or the element type of `T`).
answer
- reified requires inline; not on classes/properties
- No T() — use a factory lambda or reflection
- is List<String> only checks is List -> use typeOf<T>()
- Inlining bloats bytecode; no reflective body
- Fall back to Class<T>/KClass<T> for non-inline contexts
basics
~20 sReified can't create a T (no T()), can't be used outside inline functions or in classes, and still can't see a type's own generic arguments at runtime. Work around it with a factory lambda, a passed Class<T>/KClass<T>, or typeOf<T>() for nested generics.
solid answer
~50 sKey limits of `reified`: (1) it requires `inline` — no reified on classes, properties, constructors, or non-inline functions; (2) you cannot instantiate it directly (`T()` is illegal, since there's no guaranteed constructor) — pass a factory `() -> T` or use `T::class.java.getDeclaredConstructor().newInstance()` via reflection; (3) reification still erases the *element* generics of `T` itself — `is List<String>` only checks `is List`; for nested generics capture `typeOf<T>()` instead; (4) inlining bloats bytecode and the reified body can't be invoked reflectively, so very large or hot APIs may prefer a `Class<T>`/`KClass<T>` parameter; (5) a reified function can't be a higher-order *value* you store the way a normal function reference can in all cases, and you can't recursively call it with a non-reified type variable. Workarounds map directly: factory lambdas for construction, explicit `Class`/`KClass` parameters for non-inline or reflective contexts, `typeOf<T>()` for generic-argument awareness, and crossinline/noinline tuning for the inline cost.
code
kotlin · 9 lines// Cannot do: inline fun <reified T> create(): T = T() // illegal
// Work around construction with a factory:
inline fun <reified T> create(factory: () -> T): T = factory()
// Work around nested-generic erasure with typeOf:
import kotlin.reflect.typeOf
inline fun <reified T> elementArgs() = typeOf<T>().arguments
// elementArgs<Map<String, Int>>() -> [String, Int]go deeper
Knows you can't do T() and that reified needs inline.
Lists several limits and the basic factory-lambda workaround.
Maps each limitation to the right workaround (factory, Class/KClass, typeOf) and explains the inlining cost.
Designs library APIs choosing reified vs Class<T> deliberately, reasons about bytecode size, reflective access, and composition across module boundaries.
## What reified can and can't do Reification works by **inlining**: the compiler copies the function body to the call site and substitutes the concrete type. That mechanism creates hard limits. ### 1. Requires `inline` `reified` is only legal on type parameters of `inline` functions. You cannot have a reified type parameter on a **class**, **interface**, **property**, or **non-inline function**. A class has one runtime form, so its type args stay erased. ### 2. You cannot construct `T` ```kotlin inline fun <reified T> make(): T = T() // ERROR: no way to know T has a constructor ``` Workarounds: ```kotlin // (a) pass a factory inline fun <reified T> make(factory: () -> T): T = factory() make { User() } // (b) reflection (slower, can throw) inline fun <reified T : Any> makeReflect(): T = T::class.java.getDeclaredConstructor().newInstance() ``` ### 3. Element generics of `T` are still erased Reification gives you the **class**, not its type arguments. `is List<String>` collapses to `is List`. If you need the element type, capture it with `typeOf<T>()`: ```kotlin import kotlin.reflect.typeOf inline fun <reified T> elementType() = typeOf<T>().arguments // e.g. [String] for List<String> ``` This is exactly what serialization libraries do. ### 4. Inlining cost & no reflective body Every call site gets a copy of the body, so heavy reified functions inflate bytecode. The function has **no standalone body** to call reflectively. For large/public APIs that don't need call-site types, prefer threading a `Class<T>` or `KClass<T>`: ```kotlin fun <T : Any> load(type: KClass<T>): T = ... ``` ### 5. Composition limits A reified `T` is fixed at the call site. You cannot forward it into another reified call using a *non-reified* type variable, and storing the function as a plain reference loses the per-call type. To keep inlining benefits while limiting cost, mark heavy lambda params `crossinline`/`noinline` as appropriate. ## Decision guide - Need to **construct** T -> factory lambda (or reflection if you must). - Need **non-inline**/stored/reflective use -> pass `Class<T>`/`KClass<T>`. - Need **nested generic** info -> `typeOf<T>()`. - Just need `is`/`as`/`T::class` at the call site -> `reified` is perfect.
- If you can't put reified on a class, how do generic-aware libraries (like a typed repository) keep the type around?They accept the type as a constructor/factory argument — typically a `KClass<T>`/`Class<T>` or a captured `typeOf<T>()` — passed in from a reified inline factory function at the call site, e.g. `inline fun <reified T : Any> repo() = Repository(T::class)`.
- Why might you prefer a `Class<T>` parameter over reified even when reified would compile?To avoid bytecode bloat from inlining at many call sites, to allow non-inline/reflective use, to keep the function callable as a stored reference, and for cleaner Java interop.
saying these in an interview costs you the question
- Claiming you can write `T()` to instantiate a reified type
- Saying reified recovers element generics like List<String>
- Thinking reified can be put on a class
- Ignoring the bytecode-bloat cost of inlining
- Believing a reified function can be invoked via reflection