What does the kotlin-reflect library let you inspect at runtime that plain java.lang.reflect cannot?
answer
- @Metadata feeds kotlin-reflect
- Nullability: isMarkedNullable
- Properties reunite field+getter/setter
- isOptional = has default
- isSuspend recovers suspend
basics
~10 sKotlin reflection can see Kotlin-only details like whether a type is nullable, default parameter values, properties, and suspend functions. Plain Java reflection only sees what Java understands and misses these.
solid answer
~40 sjava.lang.reflect works at the JVM-bytecode level, so it sees classes, methods, fields and Java-visible annotations, but it is blind to Kotlin language concepts. The kotlin-reflect library reads the @Metadata annotation the Kotlin compiler attaches to every class and exposes a richer model: KClass, KProperty, KFunction, KParameter, KType. Through these you can see nullability (KType.isMarkedNullable), real Kotlin properties (val/var with getters/setters) rather than raw fields/methods, default-valued parameters (KParameter.isOptional), suspend functions, variance, type parameters, and visibility/modality as Kotlin sees them. You get Kotlin reflection from instance::class or KClass<*>, and you must add the kotlin-reflect dependency for the full API. Without it, only a limited subset works.
code
kotlin · 8 linesimport kotlin.reflect.full.memberProperties
data class User(val name: String, val nickname: String? = null)
val props = User::class.memberProperties
props.forEach { p ->
println("${p.name} nullable=${p.returnType.isMarkedNullable}")
}go deeper
Names a couple of Kotlin-only things (nullability, defaults) kotlin-reflect surfaces.
Explains @Metadata as the source and lists properties/suspend/isOptional concretely.
Distinguishes JVM bytecode model from Kotlin model and knows the bridge APIs and dependency boundary.
Reasons about when reflecting on Kotlin semantics is worth the metadata cost vs staying in Java reflection for interop or startup.
## What reflection is Reflection means inspecting and manipulating code structure (types, members, parameters) at **runtime** instead of compile time. ## Two reflection systems on the JVM - **java.lang.reflect** — built into the JDK. It models the JVM bytecode view: `Class`, `Method`, `Field`, `Constructor`, `Parameter`, plus Java-retained annotations. It knows nothing about Kotlin's source-level concepts. - **kotlin-reflect** — Kotlin's own reflection library. Its entry types are `KClass`, `KCallable`, `KFunction`, `KProperty`, `KParameter`, and `KType`. It reads the **`@Metadata`** annotation that the Kotlin compiler stamps onto every compiled class; that metadata encodes the original Kotlin signatures. ## Kotlin-only things only kotlin-reflect can see - **Nullability** — `KType.isMarkedNullable` tells you `String` vs `String?`. The JVM erases this; Java sees both as `java.lang.String`. - **Properties** — Kotlin `val`/`var` become a backing field plus getter/setter in bytecode. Java reflection sees the field and methods separately; `KProperty` reunites them as one unit with `.getter`/`.setter`. - **Default parameter values** — `KParameter.isOptional` is true when a parameter has a default. Java has no notion of defaults at all. - **suspend functions** — Kotlin compiles `suspend fun` to a method with an extra `Continuation` parameter. `KFunction.isSuspend` recovers the original intent. - **Variance, declaration-site type parameters, `reified`-era type info via `typeOf<T>()`** and Kotlin **visibility/modality** (`KVisibility`, `isOpen`, `isAbstract`). ```kotlin import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.isAccessible data class User(val name: String, val nickname: String? = null) fun main() { val kClass = User::class for (p in kClass.memberProperties) { println("${p.name}: nullable=${p.returnType.isMarkedNullable}") } // name: nullable=false // nickname: nullable=true } ``` ## How you get each - Kotlin: `instance::class`, `SomeType::class`, `::topLevelFun`, `Type::property`. - Bridge to Java: `kClass.java` (KClass -> Class), `clazz.kotlin` (Class -> KClass), and `KFunction.javaMethod`, `KProperty.javaField` from `kotlin.reflect.jvm`. ## When you still drop to java.lang.reflect When you don't need Kotlin metadata, want zero extra dependency, or interop with Java frameworks that already work in `Class`/`Method` terms.
- Where does kotlin-reflect get its Kotlin-specific information from?From the @Metadata annotation the Kotlin compiler embeds in each .class file; kotlin-reflect decodes it to reconstruct Kotlin signatures.
- Does instance::class always need the kotlin-reflect artifact?Basic ::class and simpleName/qualifiedName work without it via kotlin-stdlib, but the rich API (memberProperties, callBy, isSuspend, etc.) needs the kotlin-reflect dependency on the classpath.
Java reflection reads the compiled blueprint; kotlin-reflect also keeps the architect's original annotated drawing (@Metadata).
saying these in an interview costs you the question
- Claiming Java reflection can read Kotlin nullability or default values
- Thinking KClass and Class are the same object
- Not knowing @Metadata exists
- Assuming all KClass APIs work without the kotlin-reflect artifact