skip to content

File Structure & Top-Level Declarations

A Kotlin file can hold functions, properties, classes, and typealiases directly, with no wrapper class and no name-must-match rule. Interviewers follow up on what the JVM actually sees — the generated FileKt facade class — because that is where interop and reflection questions start.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

In Kotlin, what kinds of declarations can live at the top level of a .kt file, and how does this differ from Java?

level: juniorimportance: must knowfreq 72%

answer

  1. No wrapping class required
  2. Functions, properties, classes, objects, typealias all allowed
  3. Many public declarations per file (unlike Java)
  4. Filename independent of declared names
  5. private at top level = file-scoped

basics

~10 s

A Kotlin file can hold functions, properties (variables), classes, interfaces, objects, and type aliases directly, without putting them inside a class. Java requires almost everything to live inside a class.

solid answer

~40 s

At the top level of a .kt file you can declare functions, properties (with val/var), classes, interfaces, objects, enums, annotations, and typealiases - none need a wrapping class. This is a core difference from Java, where methods and fields must live inside a class and only one top-level public type is allowed per file. In Kotlin a single file can contain many top-level public declarations and they need not share the file's name. Top-level functions and properties are useful for utilities and constants (e.g. a maxItems property or a formatDate function) without a holder class. Visibility modifiers (public default, internal, private) apply per declaration; private means file-scoped. Top-level vals can be const if compile-time primitives or String.

code

kotlin · 8 lines
kotlin
// File: util/Format.kt
const val DASH = "-"

fun joinIds(ids: List<Int>): String = ids.joinToString(DASH)

typealias IdList = List<Int>

class Formatter   // a top-level class, sharing the file with functions

go deeper

for a junior

Knows functions and properties can sit outside a class and lists the allowed declaration kinds.

for a middle

Contrasts with Java's one-public-type rule and explains file-scoped private and internal visibility.

for a senior

Discusses module/visibility design implications and when a top-level utility beats an object or companion.

for a principal

Frames top-level declarations within API-surface and binary-compatibility tradeoffs across modules and published libraries.

## What is a top-level declaration? A *top-level* declaration is one written directly in a `.kt` file, not nested inside any class, object, or function. Kotlin removes Java's rule that code must live inside a class. ## What may appear at the top level - **Functions**: `fun greet() = "hi"` - **Properties**: `val MAX = 10` or `var counter = 0` (a property is a named value with an auto-generated getter, and a setter for `var`). - **Classes / interfaces / objects**: `class User`, `interface Repo`, `object Registry` (an `object` is a singleton). - **Enums & annotations**: `enum class Color`, `annotation class Json`. - **Type aliases**: `typealias Handler = (Event) -> Unit` - a `typealias` gives an existing type a new name; it creates no new type. ## Difference from Java In Java, methods and fields **must** be inside a class, and each source file may have **only one** top-level `public` type whose name must match the filename. Kotlin lifts both rules: a file may hold **many** public top-level declarations, and the filename is **independent** of any declared name. ## Visibility at file level Each top-level declaration takes its own visibility modifier. Default is `public`. `internal` = visible within the same Gradle/Maven module. `private` at the top level means **visible only within that file** (file-private), which is handy for helpers. ```kotlin // File: StringUtils.kt - note: no class named StringUtils const val EMPTY = "" fun String.shout(): String = uppercase() + "!" private fun helper() = 42 // visible only inside this file typealias Words = List<String> ``` ## Why it matters Top-level functions/properties let you write utilities and constants without a needless wrapper class, reducing boilerplate compared to Java's `static` helpers.

  • Can a single .kt file contain more than one public class?
    Yes. Unlike Java, Kotlin allows multiple public top-level classes (and other declarations) in one file.
  • What does `private` mean on a top-level function?
    File-private: the function is visible only within the same .kt file, not across the module or package.

A Kotlin file is like an open workbench where you can leave tools out directly, instead of Java's locked toolbox where every tool must sit inside a labeled drawer (a class).

saying these in an interview costs you the question

  • Claiming every Kotlin declaration must be inside a class like Java
  • Saying the filename must match a class name
  • Saying only one public class is allowed per file
  • Confusing top-level private with package-private (it is file-scoped)
  • Thinking top-level functions are not allowed

context

open as a page

On the JVM, how are top-level functions and properties in a file named Utils.kt compiled, and how do you call them from Java?

level: middleimportance: should knowfreq 58%

basics

~10 s

Kotlin puts all top-level functions and properties from Utils.kt into a generated class called UtilsKt. From Java you call them as static methods on UtilsKt, like UtilsKt.doThing().

open as a page

Must a Kotlin file's name match the names of the classes it declares? What are the practical conventions?

level: middleimportance: should knowfreq 49%

basics

~20 s

No. A Kotlin file can be named anything and can hold zero, one, or many classes with different names. By convention, if a file has one main class you usually name the file after it.

open as a page

What is a top-level typealias in Kotlin, what can it and can't it do, and where must it be declared?

level: seniorimportance: should knowfreq 38%

basics

~20 s

A typealias gives an existing type a shorter or clearer name. It creates no new type - it is just an alias. In Kotlin it must be declared at the top level of a file, not inside a function or class body.

open as a page

How and when are top-level properties initialized, and what risks arise from their initialization order across files on the JVM?

level: seniorimportance: nice to knowfreq 24%

basics

~20 s

Top-level properties with initializers run when their file's generated class is first loaded, top to bottom. Across different files the order is not guaranteed, so one top-level value depending on another in a different file can be null or default if loaded too early.

open as a page