Generics in Kotlin
Generics let you write code parameterized by a type and check that type at compile time. But on the JVM generics carry a hard limit — type erasure: after checking, the compiler throws the type argument away, and at runtime List<String> and List<Int> are indistinguishable. This is not an implementation detail but the cause of a whole class of restrictions that trip candidates up in interviews.
It is precisely because of erasure that you cannot write T::class.java for a plain parameter T — there is simply no class token. Kotlin offers a workaround: a reified type parameter brings the type back to runtime, but works only on inline functions. Erasure explains why the workaround is needed at all, and reified is how you use it. The full map lives in the layers below. (A separate dimension is in/out variance, but its deep dive is beyond these layers.)
Topic map
- Type erasure — why on the JVM
List<String>becomesListat runtime and what that forbids. - Reified type parameters — how
inline+reifiedbring the real type back to runtime without reflection.
Common traps
| Mistake | Consequence |
|---|---|
| Assuming a type argument survives to runtime as in C++ templates | Wrong expectations from is T, T::class, and overloads |
Writing T::class.java in an ordinary generic function | Does not compile — an erased T has no class token |
Marking a parameter reified without inline on the function | Compile error — reified is only possible under inlining |
| Declaring two overloads differing only in the type argument | A clash — after erasure they have the same JVM signature |
Trying is List<String> | Only is List<*> — the concrete argument cannot be checked |
Expecting reified T to let you create T() | The constructor is unknown — you cannot instantiate it this way |
Interview relevance
The topic is asked to check whether you understand that generics on the JVM are a purely compile-time layer erased before shipping. A candidate who explains "T::class does not work because T is erased, and reified brings the type back only thanks to inlining on an inline function" gets ahead of "well, generics store the type".
Typical checks:
- What erasure is and why at runtime
List<String>is justList. - Why
T::class.javadoes not compile for a plainT. - How
reifiedbrings the type back and why it is inseparable frominline. - Why two overloads differing only in the type argument clash.
Common wrong answer: "the JVM keeps the generic type in a hidden tag, you just need reflection to read it". In fact there is no tag — the type argument is removed; the only standard way to have the type at runtime is inline + reified or a passed Class<T>.