Show how a Kotlin `object` replaces the classic Java singleton idiom, and explain what the compiler generates for JVM/Java interop.
answer
- Java: private ctor + static getInstance (+ volatile DCL)
- Kotlin: just `object Name`
- Compiler emits `public static final INSTANCE`
- Java reaches it via Name.INSTANCE.member
- @JvmStatic / const val / @JvmField for clean Java API
basics
~20 sIn Java you wrote a private constructor and a static getInstance method. In Kotlin you just write object Name. Behind the scenes Kotlin creates one static INSTANCE field, which is how Java code reaches it.
solid answer
~40 sThe Java singleton needed: a `private` constructor, a `private static` field, and a `public static getInstance()` (often with double-checked locking). A Kotlin `object Name { ... }` replaces all of it. The compiler emits a final class with a `private` constructor and a `public static final Name INSTANCE` field initialized in the static block, so initialization is once-and-thread-safe via class loading. Kotlin call sites use `Name.member` directly. **Java** callers must go through the field: `Name.INSTANCE.member()`. To make object members callable as plain statics from Java, annotate them `@JvmStatic`, or expose constants with `const val`/`@JvmField`. This removes the hand-rolled locking boilerplate and the risk of getting double-checked locking subtly wrong.
code
kotlin · 8 linesobject IdGenerator {
private val seq = java.util.concurrent.atomic.AtomicLong()
@JvmStatic fun next(): Long = seq.incrementAndGet()
const val PREFIX = "id-"
}
// Kotlin: IdGenerator.next()
// Java: IdGenerator.next() (thanks to @JvmStatic)
// IdGenerator.PREFIX (const)go deeper
Knows object replaces the boilerplate Java singleton.
Shows the generated INSTANCE field and Java access pattern.
Adds @JvmStatic/const val/@JvmField interop and why class-init beats DCL.
Frames singletons as global state, weighing testability/DI trade-offs against convenience.
## The Java idiom being replaced ```java public final class Config { private static volatile Config instance; private Config() {} public static Config getInstance() { if (instance == null) { synchronized (Config.class) { if (instance == null) instance = new Config(); } } return instance; } public String name() { return "cfg"; } } ``` This is error-prone: forgetting `volatile`, or the second null check, breaks correctness on the JVM memory model. ## The Kotlin equivalent ```kotlin object Config { fun name() = "cfg" } // Kotlin call site: Config.name() ``` That's the entire singleton. Lazy + thread-safe initialization is handled by the JVM class-loader (see the static-init mechanism). ## What the compiler generates Roughly: - a final class `Config`, - a `private` constructor (so no one else can instantiate), - a `public static final Config INSTANCE` field, - a static initializer assigning `INSTANCE = new Config()`. ## Java interop knobs Because members live on the *instance*, Java sees them through the field by default: ```java String n = Config.INSTANCE.name(); ``` To improve the Java-facing API: - **`@JvmStatic`** on a function/property generates a real static method so Java writes `Config.name()`. - **`const val X = ...`** (compile-time constants) become `public static final` fields, inlined at use sites. - **`@JvmField`** exposes a property as a public field (no getter), useful for simple shared constants. ```kotlin object Config { const val MAX = 100 // Java: Config.MAX @JvmStatic fun name() = "cfg" // Java: Config.name() } ``` ## Why prefer the object - No locking boilerplate, no memory-model footguns. - Less code, single source of truth. - Still flexible: the object can implement interfaces and hold state. The one caution: like any singleton, an `object` is global mutable state if it holds mutable fields — that hurts testability and should be used deliberately (constants, stateless helpers, registries), not as a dumping ground.
- What does Java write to call an object function that is NOT @JvmStatic?`ObjectName.INSTANCE.func()` — it goes through the generated static `INSTANCE` field.
- Why is the Kotlin version safer than naive Java?It relies on guaranteed once-only class initialization, so there's no risk of getting double-checked locking or `volatile` wrong.
saying these in an interview costs you the question
- Saying Java calls an object's method directly as Name.method() without @JvmStatic
- Forgetting the generated INSTANCE field exists
- Claiming you still need to write getInstance in Kotlin
- Not acknowledging the testability cost of global singletons