skip to content

Syntax Basics

The structural rules of a .kt file: what can live at the top level, where the program starts, which constructs are expressions, and how packages, imports, and visibility are declared. These are the questions that reveal whether you understand Kotlin's file model or assume Java's one-class-per-file convention.

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

explore

questions

27

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

What is the entry point of a Kotlin program, and what are the valid signatures for `main`?

level: juniorimportance: must knowfreq 75%

basics

~10 s

Every Kotlin program starts in a function called main. You can write fun main() with no parameters, or fun main(args: Array<String>) to receive command-line arguments. The runtime calls it automatically to begin execution.

open as a page

In Kotlin, must a file's package declaration mirror its directory structure on disk? Explain what the compiler actually requires.

level: juniorimportance: must knowfreq 55%

basics

~20 s

No. In Kotlin the package name does not have to match the folder path. The compiler accepts any package name regardless of where the file lives, though matching folders to packages is still recommended for clarity.

open as a page

What is the default visibility of a top-level declaration in Kotlin, and how does that compare to Java?

level: juniorimportance: must knowfreq 60%

basics

~10 s

By default everything in Kotlin is public — visible everywhere. In Java, members with no modifier are package-private (visible only in the same package). Kotlin has no package-private at all.

open as a page

Are semicolons required in Kotlin? When, if ever, do you actually need one?

level: juniorimportance: must knowfreq 55%

basics

~20 s

No. Kotlin ends statements at line breaks, so you almost never write a semicolon. You only need one to put two statements on the same line, like val a = 1; val b = 2.

open as a page

In Kotlin, why is there no ternary operator (cond ? a : b), and how do you write the equivalent?

level: juniorimportance: must knowfreq 70%

basics

~10 s

In Kotlin an if returns a value, so you just write val x = if (cond) a else b. Because if already gives a result, a separate ?: ternary operator is not needed.

open as a page

What kinds of declarations can a Kotlin `import` statement bring into scope? Give examples beyond classes.

level: middleimportance: must knowfreq 60%

basics

~10 s

In Kotlin, import works for more than classes. You can import top-level functions, top-level properties, enum entries, object members, and even nested classes—anything with a fully qualified name.

open as a page

Compare `internal` and `private` for top-level declarations. What exactly is the scope of each?

level: middleimportance: must knowfreq 50%

basics

~10 s

internal means visible to all code in the same module (your compiled unit). private on a top-level declaration means visible only inside the same file. Both hide the declaration from outside consumers.

open as a page

What is `Unit` in Kotlin, how does it differ from Java's `void`, and where does it appear?

level: middleimportance: must knowfreq 60%

basics

~20 s

Unit is Kotlin's 'no meaningful result' type. A function that doesn't return anything useful returns Unit. Unlike Java's void keyword, Unit is a real type with a single value, so it can be used in generics and lambdas.

open as a page

How does `when` behave as an expression, and what exhaustiveness rules apply to it?

level: middleimportance: must knowfreq 65%

basics

~20 s

when can return a value, so you can assign its result. When used as an expression it must cover every possible case — usually by adding an else branch, or covering all options of an enum or sealed type.

open as a page

Which packages are imported by default in every Kotlin file, and why does that matter for things like `println` or `listOf`?

level: juniorimportance: should knowfreq 45%

basics

~10 s

Kotlin auto-imports some packages into every file, like kotlin., kotlin.collections., and kotlin.io.*. That's why you can call println, listOf, or use String without writing any import.

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

How do you read command-line arguments and set a process exit code from a Kotlin `main`?

level: middleimportance: should knowfreq 45%

basics

~10 s

Command-line arguments arrive as the args: Array<String> parameter of main. To end the program with a specific status code, call kotlin.system.exitProcess(code) — for example exitProcess(1) to signal failure.

open as a page

What is `suspend fun main` and when would you use it?

level: middleimportance: should knowfreq 55%

basics

~20 s

suspend fun main lets the program's entry point call suspending coroutine functions directly, without manually creating a runBlocking block. The runtime starts a coroutine for you and waits until it finishes before the program exits.

open as a page

Explain Kotlin's `import ... as` aliasing. When is it necessary, and what exactly does the alias rename?

level: middleimportance: should knowfreq 50%

basics

~10 s

Import aliasing lets you rename something on import, e.g. import a.Foo as Bar. It's mainly used to resolve name clashes between two classes or functions with the same simple name from different packages.

open as a page

What are trailing commas in Kotlin, where are they allowed, and why are they useful?

level: middleimportance: should knowfreq 35%

basics

~20 s

A trailing comma is a comma after the last item in a list, like f(a, b,). Kotlin allows it in many comma-separated lists. It makes adding/removing/reordering lines easier and produces cleaner diffs in version control.

open as a page

Why can't you write `val b = (a = 5)` or use an assignment/loop as a value in Kotlin?

level: middleimportance: should knowfreq 35%

basics

~20 s

In Kotlin, assignments and loops are statements, not expressions, so they don't produce a value you can store. That's why val b = (a = 5) doesn't compile and you can't use a for/while loop on the right side of =.

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 does the JVM locate and invoke a Kotlin top-level `main`, given the JVM only knows `public static void main(String[])` inside a class?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Kotlin compiles a file like App.kt into a JVM class named AppKt and generates a hidden static main(String[]) method inside it. The JVM launches that class, and that generated method calls your real top-level main.

open as a page

When two declarations with the same simple name are reachable (e.g., one via wildcard import, one in the same package), how does Kotlin resolve the reference, and how do you force a specific one?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Kotlin prefers names in the same package and explicit (named) imports over wildcard imports. If there's a true ambiguity, it's a compile error, and you fix it by using an explicit import, an as alias, or a fully qualified name.

open as a page

How does the Kotlin compiler enforce `internal` visibility on the JVM, and what are the interop and reflection consequences?

level: seniorimportance: should knowfreq 25%

basics

~20 s

The JVM has no 'module' concept, so Kotlin renames internal functions in bytecode by adding a module suffix. Other modules can't call them by their normal name. But Java code or reflection can still reach them using the mangled name.

open as a page

What is the difference between an expression-body function (`fun f() = ...`) and a block-body function, and when does return-type inference apply?

level: seniorimportance: should knowfreq 50%

basics

~20 s

An expression-body function uses = and a single expression as its whole body, and its return type can be inferred. A block-body function uses { } and must use return for any non-Unit result, with the return type usually written explicitly.

open as a page

Can a `try`/`catch` block be used as an expression in Kotlin? How is its value determined?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Yes. A try/catch can return a value. If the try block succeeds, its last expression is the result; if it throws and a catch handles it, that catch block's last expression is the result. A finally block never affects the value.

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

Compare Kotlin's program-entry model to Java's, and discuss design implications of allowing a top-level / expression-body `main`.

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Java forces main to be a static method inside a class; Kotlin lets it be a free top-level function and even a one-line expression body. This reduces ceremony, but you must point your tooling at the generated file class instead of a function name.

open as a page

You're authoring a Kotlin library where the default `public` visibility risks leaking implementation details. What language/tooling mechanisms help control the public API surface?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

Turn on Kotlin's explicit-API mode so the compiler forces you to label every public declaration on purpose. Mark internals with internal or private, and use tools that track your public API so accidental changes are caught.

open as a page