skip to content

What does `KClass.objectInstance` return, and how does it behave for objects vs regular classes?

level: middleimportance: should knowfreq 45%

answer

  1. objectInstance returns the singleton, else null
  2. non-object class -> null, not an exception
  3. great with sealedSubclasses.mapNotNull
  4. needs kotlin-reflect at runtime
  5. reading it initializes the object (side effect)

basics

~10 s

objectInstance gives you the single shared instance of a Kotlin object (a singleton). If the KClass is for an object declaration it returns that instance; for an ordinary class it returns null.

solid answer

~40 s

`KClass<T>.objectInstance` is a nullable property (`T?`) that returns the singleton instance when the `KClass` represents a Kotlin `object` declaration (a `companion object`, a named `object Foo`, or an anonymous-but-named object), and `null` otherwise. It lets reflective code resolve a singleton without knowing its name: `MyService::class.objectInstance` returns the lone `MyService` instance, while `String::class.objectInstance` is `null` because `String` is a regular class. This is invaluable when, for example, you scan `sealedSubclasses` and need the actual instances of the object-typed variants. Accessing `objectInstance` requires the `kotlin-reflect` dependency at runtime — it is part of the full reflection surface, not the stdlib stub. It triggers class initialization (the object is created lazily on first access of the underlying JVM `INSTANCE` field).

code

kotlin · 8 lines
kotlin
sealed interface State
object Idle : State
object Running : State
data class Error(val msg: String) : State

fun objectStates(): List<State> =
    State::class.sealedSubclasses.mapNotNull { it.objectInstance }
// [Idle, Running]

go deeper

for a junior

Knows object is a singleton and that objectInstance retrieves it.

for a middle

Knows it returns null for non-objects and pairs it with sealedSubclasses.mapNotNull.

for a senior

Aware of the kotlin-reflect requirement and the class-initialization side effect.

for a principal

Designs serialization/registry layers that branch on object vs class variants without leaking reflection cost into hot paths.

## The property `objectInstance: T?` is a member of `KClass<T>`. It answers: *if this class is a singleton `object`, give me that instance*. - For an `object` declaration -> returns the singleton. - For a normal `class`, `interface`, `enum`, etc. -> returns `null`. ## What counts as an object Kotlin's `object` keyword declares a singleton — a class with exactly one instance, created lazily and held in a synthetic JVM `INSTANCE` field. Named objects (`object Config`), `companion object`s, and object expressions assigned to a declaration all qualify. ```kotlin object Config { val env = "prod" } class Service fun main() { println(Config::class.objectInstance) // Config@... (the singleton) println(Service::class.objectInstance) // null } ``` ## Why it matters: pairing with sealed hierarchies A very common pattern is a sealed hierarchy where some variants are objects (no state) and some are classes (with data). Reflection lets you turn the type list into usable instances: ```kotlin sealed interface Event object Started : Event object Stopped : Event data class Failed(val cause: String) : Event fun singletonEvents(): List<Event> = Event::class.sealedSubclasses.mapNotNull { it.objectInstance } // -> [Started, Stopped] (Failed has no objectInstance -> filtered out) ``` `mapNotNull` discards the `null`s coming from the non-object subclass `Failed`. ## Runtime requirements `objectInstance` is part of the *full* reflection API and needs the `org.jetbrains.kotlin:kotlin-reflect` artifact on the classpath; the lightweight stdlib `KClass` (used for `simpleName`/`qualifiedName`/identity) does not implement it. Calling it on a non-object simply returns `null` — it does not throw. ## Initialization side effect Reading `objectInstance` forces the JVM to load and initialize the object class, running its property initializers and `init` block. So it is not purely a metadata read — it can have observable side effects. ## Contrast - `objectInstance` -> the instance (or null). - `isCompanion` / `isData` / `isSealed` etc. -> boolean class-kind flags. - Calling a constructor reflectively is a different path entirely (and would fail for an object, which has no public constructor).

  • What does `objectInstance` return for a regular `class`?
    `null`; it never throws for non-objects.
  • Does reading `objectInstance` have side effects?
    Yes — it forces class initialization of the object, running its init block and field initializers.

saying these in an interview costs you the question

  • Saying it throws for non-object classes (it returns null)
  • Confusing `objectInstance` with reflectively calling a constructor
  • Forgetting it needs kotlin-reflect at runtime
  • Assuming it works on enum entries the same way (use enum's own values instead)

context