How do @JvmName and @JvmMultifileClass change the file facade, and when would you use them?
answer
- @file:JvmName renames the facade (above package)
- @file:JvmMultifileClass merges many files into one facade
- Both annotations on EVERY file, same JvmName
- Only affects Java view; Kotlin unaffected
- Renaming = binary-incompatible for Java
basics
~10 s@JvmName renames the generated facade class so Java callers see a nicer name. @JvmMultifileClass lets several files share one facade class, so functions split across files appear under a single name to Java.
solid answer
~40 sBy default the facade class name is `<FileName>Kt`, which is often ugly for Java consumers. Putting a **file-level** annotation `@file:JvmName("StringUtils")` at the top of the file (before the `package` directive) renames the generated facade — Java then calls `StringUtils.foo()` instead of `MyKotlinFileKt.foo()`. If you want top-level functions spread across **multiple files** to appear under **one** Java class, you combine `@file:JvmName("...")` with `@file:JvmMultifileClass` on each contributing file; the compiler merges them into a shared facade. This is exactly how the standard library exposes e.g. `kotlin.collections.CollectionsKt`-style grouping cleanly. These annotations affect only the JVM-facing name; Kotlin call sites are unaffected. Misuse risk: renaming the facade is a binary-compatibility change for Java callers.
code
kotlin · 17 lines// File: TextA.kt
@file:JvmName("TextUtils")
@file:JvmMultifileClass
package com.example
fun trimAll(s: String) = s.trim()
// File: TextB.kt
@file:JvmName("TextUtils")
@file:JvmMultifileClass
package com.example
fun pad(s: String, n: Int) = s.padStart(n)
// Java sees a single class:
// TextUtils.trimAll(" x ");
// TextUtils.pad("x", 3);go deeper
Likely unaware these annotations exist; may only know the default Kt facade.
Knows @file:JvmName renames the facade for Java but may miss the multifile merge requirements.
Correctly applies both file-level annotations, explains the merge mechanics and the @file: target rule.
Weighs Java API ergonomics vs binary-compatibility risk and designs facade naming as a stable public contract.
## The default and its problem A top-level function compiles into a facade named `<FileName>Kt`. For Java consumers, names like `StringExtensionsKt` are noisy, and you cannot split a logically-single API across multiple files without each file producing its own facade. ## `@JvmName` — rename the facade Apply it as a **file-level** annotation, placed **above the `package` directive**: ```kotlin @file:JvmName("StringUtils") package com.example fun shout(s: String) = s.uppercase() ``` Now the generated class is `com.example.StringUtils`, so Java writes `StringUtils.shout("hi")` instead of `StringUtilsKt.shout(...)`. The `@file:` **use-site target** is mandatory here — it tells the compiler the annotation applies to the whole file/facade, not to a single declaration. (Note: `@JvmName` on an individual `fun` renames *that method*, used to dodge JVM signature clashes; on a *file* it renames the *facade class*. Same annotation, two targets.) ## `@JvmMultifileClass` — merge facades If an API is large, you may want to keep Kotlin source in several files but present **one** Java class. Add **both** annotations to **each** file, using the **same** `@JvmName`: ```kotlin // File: ListsCore.kt @file:JvmName("Lists") @file:JvmMultifileClass package com.example fun first2(...) { } // File: ListsExtra.kt @file:JvmName("Lists") @file:JvmMultifileClass package com.example fun last2(...) { } ``` The compiler generates a single public `com.example.Lists` facade that delegates to per-file part classes. Java sees `Lists.first2(...)` and `Lists.last2(...)` as if from one class. The Kotlin standard library uses exactly this pattern (e.g. the `kotlin.collections` helpers). ## Rules and gotchas - Both annotations are **file-level** (`@file:`) and must sit above `package`. - For multifile merging, **every** participating file needs **both** annotations with the **identical** JvmName; otherwise you get a duplicate-class or split-facade error. - You **cannot** have a top-level declaration whose facade name collides with a real class of the same name. - Changing or removing these names is a **binary-incompatible** change for Java callers (Kotlin callers are unaffected because they never reference the facade). ## When to use - Library authors exposing a clean Java API surface. - Grouping a big helper API into readable source files without fragmenting the Java-visible class. - Pure-Kotlin internal code rarely needs either annotation.
- Why must @JvmMultifileClass appear on every contributing file?Each file independently produces facade bytecode; the compiler only merges files that opt in with the same JvmName and the multifile annotation.
- Does @file:JvmName affect how Kotlin code calls the function?No. Kotlin resolves by package and symbol, ignoring the facade name; only Java callers see the renamed class.
saying these in an interview costs you the question
- Putting @JvmName on the function when the goal is to rename the facade
- Forgetting @file: use-site target or placing it after package
- Omitting @JvmMultifileClass on some files in the group
- Claiming the rename affects Kotlin call sites
- Ignoring that renaming breaks existing Java callers