What is a KClass in Kotlin reflection, how do you obtain one, and how does it differ from java.lang.Class?
answer
- ::class gives KClass, ::class.java gives Class
- Bound (instance::class) vs literal (Type::class)
- .java and .kotlin bridge the two worlds
- isData/isSealed/objectInstance are Kotlin-only
- Full introspection needs kotlin-reflect on classpath
basics
~20 sA KClass is Kotlin's runtime handle to a class. You get it with String::class for a type or instance::class for an object. It exposes Kotlin features like properties and nullability; java.lang.Class only knows the Java view.
solid answer
~40 sKClass<T> is the entry point of Kotlin reflection, representing a class at runtime. You obtain one with a class literal (String::class) or from an instance (myObj::class). KClass exposes Kotlin-specific members: members (KCallable), declaredMemberProperties, constructors, isData, isSealed, objectInstance, plus visibility and nullability info. java.lang.Class is the JVM view and misses Kotlin concepts (no notion of data/sealed, properties, or nullable types). You bridge between them with .java (KClass to Class) and .kotlin (Class to KClass). Basic class references like String::class are bound metadata and need only the runtime; richer introspection (members, parameters) requires the separate kotlin-reflect artifact on the classpath, otherwise calls throw KotlinReflectionNotSupportedError.
code
kotlin · 13 linesimport kotlin.reflect.KClass
import kotlin.reflect.full.declaredMemberProperties
data class User(val id: Long, val name: String)
fun main() {
val kc: KClass<User> = User::class
println(kc.isData) // true
println(kc.simpleName) // User
kc.declaredMemberProperties.forEach { println(it.name) } // id, name
val jc: Class<User> = kc.java // bridge to java.lang.Class
println(jc.name) // fully qualified Java name
}go deeper
Knows ::class returns a KClass and ::class.java returns the Java Class.
Explains bound vs literal references and the .java/.kotlin bridge plus Kotlin-only flags.
Discusses the kotlin-reflect dependency boundary and the performance/cost of reflective access.
Reasons about when to avoid reflection entirely (startup cost, GraalVM native-image, security) and prefer compile-time alternatives.
## What is KClass `KClass<T>` is the central type of the **Kotlin reflection** API. It is a runtime representation of a class or interface — analogous to Java's `java.lang.Class`, but it understands Kotlin-only concepts. ## Obtaining a KClass There are two forms of the `::class` operator: - **Bound class reference** — from an instance: `instance::class` gives the *runtime* class of that object. - **Class literal** — from a type: `String::class` gives the class for that declared type. ```kotlin val a: KClass<String> = String::class // class literal val s: Any = "hi" val b: KClass<out Any> = s::class // bound reference -> String::class at runtime ``` ## What KClass exposes - `simpleName`, `qualifiedName` - `members` / `declaredMemberProperties` / `declaredMemberFunctions` — collections of `KCallable` - `constructors`, `primaryConstructor` - Kotlin flags: `isData`, `isSealed`, `isAbstract`, `isCompanion`, `isInner`, `isFun` - `objectInstance` — the singleton for an `object` declaration - `sealedSubclasses`, `supertypes`, `visibility` ## Difference from java.lang.Class `java.lang.Class` is the JVM-level view. It has no concept of Kotlin data/sealed classes, properties (it sees getter/setter methods), nullability, or `object` singletons. You convert between the two: ```kotlin val jc: Class<String> = String::class.java // KClass -> Class val kc: KClass<String> = jc.kotlin // Class -> KClass ``` ## kotlin-reflect dependency Simple references compile into lightweight metadata, but full introspection (`members`, `primaryConstructor`, calling things) needs the **`kotlin-reflect`** library on the classpath. Without it, those calls fail with `KotlinReflectionNotSupportedError`. Reflection is also slower than direct calls, so use it sparingly.
- Why might String::class.members throw at runtime even though it compiles fine?Full member introspection requires the kotlin-reflect artifact on the classpath; without it the call throws KotlinReflectionNotSupportedError.
- What's the difference between String::class and a value of type KClass<out Any> from someAny::class?The literal is statically String::class; the bound reference resolves to the object's actual runtime class, so its static type is KClass<out Any>.
KClass is the Kotlin-language passport for a type; java.lang.Class is the older JVM ID card that omits the Kotlin-specific stamps.
saying these in an interview costs you the question
- Thinking KClass and java.lang.Class are the same object
- Claiming reflection works fully with no extra dependency
- Confusing ::class (KClass) with ::class.java (Class)
- Saying java.lang.Class knows about data/sealed classes
- Not knowing instance::class returns the runtime class