skip to content

A Kotlin file Utils.kt declares a top-level function fun greet(): String. How does Java call it, and where does that method actually live on the JVM?

level: juniorimportance: must knowfreq 65%

answer

  1. File name + 'Kt' = facade class
  2. Utils.kt -> UtilsKt.greet()
  3. @file:JvmName renames the facade
  4. @file:JvmMultifileClass merges files
  5. Properties become getters; const = static final

basics

~10 s

Kotlin puts top-level functions into an auto-generated class named after the file plus 'Kt'. So Utils.kt's greet() is called from Java as UtilsKt.greet().

solid answer

~30 s

Top-level (file-level) Kotlin functions and properties have no enclosing class, but the JVM requires every method to live in a class. The compiler generates a synthetic 'file facade' class named `<FileName>Kt` — for `Utils.kt` that's `UtilsKt`. The function becomes a public static method on it, so Java calls `UtilsKt.greet()`. You can override the generated name with `@file:JvmName("Greetings")` at the top of the file, making it `Greetings.greet()`. Multiple files can merge into one facade with `@file:JvmMultifileClass` plus a shared `@file:JvmName`. From Kotlin you just call `greet()`; the facade is invisible there.

code

kotlin · 8 lines
kotlin
@file:JvmName("Greetings")
package com.acme

fun greet(): String = "hi"
const val VERSION = "1.0"
// Java:
// Greetings.greet();    // facade renamed
// Greetings.VERSION;    // const -> static final

go deeper

for a junior

Knows top-level functions live on a FileNameKt facade and calls UtilsKt.greet().

for a middle

Explains the naming rule, getter generation for properties, and @file:JvmName renaming.

for a senior

Uses @file:JvmMultifileClass to design a clean, stable Java-facing utility surface across files.

for a principal

Standardizes facade naming/merging across modules so renames don't break downstream Java binary compatibility.

## The problem the facade solves Kotlin allows **top-level declarations** — functions and properties written directly in a file, not inside any class. The JVM has no concept of a method outside a class, so the Kotlin compiler must put them somewhere. ## The FooKt facade class For a file `Utils.kt`, the compiler generates a `final class UtilsKt` (the **file facade**) and emits each top-level function as a `public static` method: ```kotlin // Utils.kt fun greet(): String = "hi" val VERSION = "1.0" ``` From Java: ```java String s = UtilsKt.greet(); String v = UtilsKt.getVERSION(); // property -> getter ``` The naming rule: **file name + `Kt` suffix**, with the first letter capitalized. `string-helpers.kt` becomes `StringHelpersKt`. ## Renaming the facade: @file:JvmName The `Kt` suffix is ugly for Java consumers. Put a file-level annotation at the very top (before `package`): ```kotlin @file:JvmName("Greetings") package com.acme fun greet(): String = "hi" ``` Now Java calls `Greetings.greet()`. ## Merging files: @file:JvmMultifileClass To spread one Java-facing class across several `.kt` files, give them the SAME `@file:JvmName` and add `@file:JvmMultifileClass` to each. The compiler merges them into one facade. ## Top-level properties - A normal `val`/`var` becomes a static field with a getter (and setter for `var`): `getVERSION()`. - A `const val` becomes a public static final field accessible directly as `UtilsKt.VERSION` (no getter). - `@JvmField` on a non-const top-level property exposes the field directly too. ## Key terms - **top-level declaration**: a function/property outside any class. - **file facade / `FooKt`**: the synthetic class holding those members for the JVM. - **`@file:JvmName`**: renames the facade class. - **`@file:JvmMultifileClass`**: merges multiple files into one facade.

  • How does Java call a top-level `const val MAX = 10`?
    As a static final field: `UtilsKt.MAX` (or the renamed facade). No getter is generated for const.
  • What if two files need to share one Java class name?
    Give both the same `@file:JvmName` and add `@file:JvmMultifileClass` to each; they merge into one facade.

Top-level functions are homeless on the JVM, so the compiler builds them a house called FooKt and moves them in as static residents.

saying these in an interview costs you the question

  • Saying top-level functions are global statics with no class
  • Forgetting the 'Kt' suffix or the capitalization rule
  • Putting @file:JvmName after the package declaration
  • Assuming Java sees the function in the package scope directly

context