What does the @JvmStatic annotation do, and why would a Kotlin author add it to a companion object function?
answer
- No static in Kotlin → companion object is a real singleton
- Default: Java must write Foo.Companion.bar()
- @JvmStatic emits a real static method on outer class
- Java then writes Foo.bar()
- Interop-only; Kotlin call sites unchanged
basics
~10 s@JvmStatic tells the Kotlin compiler to also generate a real static method. Then Java code can call Foo.bar() directly instead of the longer Foo.Companion.bar().
solid answer
~40 sKotlin has no static members; their replacement is the companion object or a named object, which is a real singleton instance. By default a companion function compiles to an instance method on the Companion singleton, so Java must write Foo.Companion.bar(). Adding @JvmStatic makes the compiler ALSO emit a genuine static method bar() on the outer class Foo, so Java can call Foo.bar(). It is purely an interop convenience: it changes the generated JVM bytecode (adds a static method/field) but does not affect Kotlin call sites, which already use Foo.bar(). It applies to companion-object and named-object members (functions and properties). Without it, Java interop with Kotlin 'static-like' members is verbose and surprising.
code
kotlin · 6 linesclass MathUtil {
companion object {
@JvmStatic fun square(x: Int) = x * x // Java: MathUtil.square(3)
fun cube(x: Int) = x * x * x // Java: MathUtil.Companion.cube(3)
}
}go deeper
Knows it lets Java call Foo.bar() instead of Foo.Companion.bar() and that Kotlin has no static.
Explains the generated Companion singleton and that the annotation is additive bytecode for Java interop.
Distinguishes the default instance-method-on-Companion emission from the added static, covers properties and named objects.
Frames it within an interop API-design policy and weighs it against alternatives like top-level functions or @JvmField.
## The problem: Kotlin has no `static` Kotlin removed the `static` keyword. Where Java uses static members, Kotlin uses a **companion object** (one per class, declared with `companion object { ... }`) or a **named object** (`object Foo { ... }`, a singleton). Both are real objects — instances — not static containers. ## What the compiler emits by default Given: ```kotlin class Foo { companion object { fun bar() = 42 } } ``` The compiler creates a nested class `Foo$Companion` and a single static field `Foo.Companion` holding that singleton. `bar()` becomes an **instance** method on `Foo$Companion`. From Kotlin you write `Foo.bar()` and the compiler routes it through the singleton automatically. From **Java**, though, there is no such sugar, so you must write the verbose, surprising: ```java Foo.Companion.bar(); ``` ## What `@JvmStatic` changes Annotating the member with `@JvmStatic`: ```kotlin class Foo { companion object { @JvmStatic fun bar() = 42 } } ``` tells the compiler to **also** emit a real `static` method `bar()` directly on the **outer class** `Foo`. Now Java can call: ```java Foo.bar(); // clean — calls the generated static method ``` The `Foo.Companion.bar()` form still exists too; `@JvmStatic` is purely additive at the bytecode level. ## Key facts - It affects **only generated JVM bytecode for Java callers**. Kotlin call sites already used `Foo.bar()` and are unchanged. - It works on members of a **companion object** or a **named `object`**. - It applies to **functions and properties** (for a property it generates a static getter/setter). - It is one of several JVM interop annotations alongside `@JvmField`, `@JvmName`, `@JvmOverloads`, and `@Throws`.
- Does @JvmStatic change how Kotlin code calls the function?No. Kotlin already calls Foo.bar() regardless; @JvmStatic only adds a static method in the bytecode for Java's benefit.
- Can you put @JvmStatic on a top-level function?No. Top-level functions already compile to static methods on a file class, so @JvmStatic is neither needed nor allowed there.
It's like adding a direct front-door shortcut so visitors (Java) don't have to walk around to the side entrance (Companion) every time.
saying these in an interview costs you the question
- Claiming Kotlin has a static keyword
- Thinking @JvmStatic changes Kotlin call syntax
- Saying the Companion form stops working after adding it
- Confusing it with @JvmField (which is about fields, not methods)
- Believing it makes the function faster for Kotlin callers