Explain exactly what @JvmStatic does when placed on a companion member, what it does NOT change, and how a named companion object affects the Java access path.
answer
- @JvmStatic = adds a static delegate, not a move
- Companion field still present after @JvmStatic
- Kotlin call sites unaffected
- Named companion: Foo.Factory.x()
- One companion per class
basics
~20 s@JvmStatic makes Kotlin emit an extra real static method on the outer class, so Java skips Companion. It doesn't remove the Companion object. Naming the companion changes 'Companion' to that name in the access path.
solid answer
~40 s`@JvmStatic` on a companion function or property tells the compiler to ADD a genuine JVM `static` method/accessor on the enclosing class that delegates to the companion instance. So `Foo.create()` works from Java instead of only `Foo.Companion.create()`. What it does NOT do: it does not delete the `Companion` field or nested class — both access paths remain valid; and it does not affect Kotlin call sites, which already write `Foo.create()`. For properties it generates static accessors (`getX()`/`setX()`). A NAMED companion — `companion object Factory { }` — replaces the default `Companion` identifier: Java writes `Foo.Factory.create()` (or `Foo.create()` if @JvmStatic is also present). You can only have one companion per class, named or not.
code
kotlin · 11 linesclass Foo {
companion object Factory {
@JvmStatic fun create(): Foo = Foo()
fun build(): Foo = Foo()
}
}
// Java:
// Foo.create(); // @JvmStatic delegate
// Foo.Factory.create(); // named companion path
// Foo.Factory.build(); // only path for build()
// Foo.build(); // does NOT compilego deeper
Knows @JvmStatic lets Java call Foo.create() instead of Foo.Companion.create().
Articulates that the Companion field/class remain and Kotlin call sites are unchanged, plus named-companion paths.
Explains delegation/state-sharing and chooses named companions to express sub-namespaces for Java consumers.
Defines when @JvmStatic + naming is part of the public API contract to keep Java ergonomics stable across releases.
## @JvmStatic precisely `@JvmStatic` is an annotation you put on a member of a `companion object` (or a named `object`). It instructs the Kotlin compiler to generate an **additional** JVM `static` method on the OUTER class that forwards to the companion's instance method. ```kotlin class Foo { companion object { @JvmStatic fun create(): Foo = Foo() var counter: Int = 0 @JvmStatic get @JvmStatic set } } ``` Generated Java-visible surface on `Foo`: - `static Foo create()` - `static int getCounter()`, `static void setCounter(int)` ### What stays the same (what @JvmStatic does NOT do) - The `Companion` nested class and the `public static final Foo$Companion Companion` field STILL exist. `Foo.Companion.create()` is still valid. - Kotlin call sites are unchanged — `Foo.create()` already worked in Kotlin regardless. - It does not make the member a top-level/global function; it stays logically a companion member. - The generated static simply delegates: it calls the single companion instance, so state is shared. ## Named companion objects A companion may be named: ```kotlin class Foo { companion object Factory { fun create(): Foo = Foo() } } ``` Now the JVM field/nested class is `Factory`, so Java writes: ```java Foo.Factory.create(); ``` With `@JvmStatic` added, `Foo.create()` also works. The name improves readability when the companion is a logical sub-namespace (e.g., `Factory`, `Parser`). ### Constraints - **Only one companion object per class** (named or anonymous). - `@JvmStatic` also works on members of regular (non-companion) `object` declarations and on interface companion members (with caveats). - For properties, you can annotate the property, or individual `get`/`set`. ## Mental model Think of the companion as the real owner of the member; `@JvmStatic` just stamps a convenient static shortcut onto the class, while the named companion renames the doorway Java walks through.
- If two companion functions share state, does @JvmStatic break that?No. The generated static delegates to the single companion instance, so shared state is preserved.
- Can a class have both a named and an anonymous companion?No — a class may have at most one companion object, named OR anonymous.
saying these in an interview costs you the question
- Saying @JvmStatic removes the Companion field
- Claiming @JvmStatic changes Kotlin call syntax
- Thinking you can declare two companions
- Believing a named companion forbids @JvmStatic
- Assuming @JvmStatic copies state into a separate static