skip to content

Kotlin

3 roadmaps1,876 questionsupdated

Kotlin as interviewers actually probe it: null safety baked into the type system, data classes and sealed hierarchies, extension functions and DSL-shaped lambdas, structured-concurrency coroutines, and the Java interop seams underneath it all. It is the default language for Android and a common choice for JVM backends, so most JVM teams ask about it.

on this pageshow

guide

overview

~2 min

Kotlin interviews check whether you write the language the way it was designed or as Java with shorter syntax. Expect the opening minutes on how the compiler tracks absence, followed by the object model — data classes, sealed hierarchies, objects and companions — and then idiomatic function style: extensions, scope functions, lambdas with receivers. Any role that touches asynchronous work, whether an Android screen or a JVM service, spends a long stretch on coroutines and Flow, where cancellation and error propagation expose who has shipped concurrent code and who has only read about it. Senior rounds turn to trade-offs: why `inline` exists, when a sequence beats a list, why the ecosystem prefers generating code at compile time to reflecting at runtime. The hub follows those seams. The language core is [Fundamentals](/topics/lang-kotlin-fundamentals), [Null Safety](/topics/lang-kotlin-null-safety), the [Type System](/topics/lang-kotlin-type-system), [Classes & Objects](/topics/lang-kotlin-classes), [Functions](/topics/lang-kotlin-functions) and [Functional Features](/topics/lang-kotlin-functional). Everyday library work sits in [Collections & Sequences](/topics/lang-kotlin-collections), the [Standard Library](/topics/lang-kotlin-stdlib) and [DSLs & Type-Safe Builders](/topics/lang-kotlin-dsls). Concurrency is [Coroutines](/topics/lang-kotlin-coroutines) and then [Flow](/topics/lang-kotlin-flow). The platform boundaries are [Java Interop](/topics/lang-kotlin-interop) and [Multiplatform](/topics/lang-kotlin-multiplatform), and the working-engineer layer is [Tooling & Build](/topics/lang-kotlin-tooling), [Testing](/topics/lang-kotlin-testing) and [Reflection, Annotations & Serialization](/topics/lang-kotlin-reflection). Learn it roughly in that order. Fundamentals and null safety come first, because almost every later answer assumes you read `if` as an expression and `T?` as a distinct type. Classes and functions next, since they are the bulk of daily code, then functional features and collections. Leave coroutines until lambdas, receivers and inline functions feel routine: the concurrency API is built from them, and gaps there make its questions look harder than they are. Pick up interop alongside the core, because platform types appear the first time you call a Java library. Multiplatform, tooling and testing carry the most weight when the role names them: a mobile team sharing code with iOS, or a backend team that expects you to own the build.

primer

### Absence is a type, not a runtime accident Kotlin splits every type into a non-null and a nullable variant, and the compiler refuses unchecked use of the nullable one. The operators (`?.`, `?:`, `!!`), smart casts after a check, and `lateinit` are all tools for moving a value from one side of that split to the other. The guarantee is weakest at the Java boundary, where values arrive as platform types and the checking is on you. ### Closed and read-only by default Classes and members are `final` unless marked `open`; `val` is the binding you reach for first; `List`, `Set` and `Map` expose no mutators. These choices invert Java's habits, and interviewers probe the consequences: frameworks that proxy classes by subclassing them, read-only views that are not truly immutable, and `sealed` hierarchies that let the compiler check a `when` for exhaustiveness. ### Almost everything is an expression `if`, `when` and `try` produce values, functions can have expression bodies, and `Nothing` is the type of an expression that never completes, such as `throw`. This is why Kotlin reads as a chain of values rather than a sequence of assignments, and why so many idioms fit on one line. ### The compiler writes the boilerplate — know what it writes Properties get generated accessors, data classes get generated equality and copying, `by` generates forwarding for interface and property delegation, and default arguments stand in for overload sets. Many intermediate questions are really asking what the generated code looks like and which inputs it uses. ### Functions are values, and receivers are the trick Extension functions are static functions with a member-style call site: they add nothing to the class and are resolved against the declared type. Lambdas with receivers let a block run as if it were inside another object; scope functions, builders and most Kotlin DSLs rest on that one feature. `inline` makes the style cheap by removing the lambda object, and it also unlocks non-local returns and `reified` type parameters. ### Concurrency is structured A coroutine is a computation that can suspend without holding a thread, and it is launched from a scope. Scopes form a parent–child tree, so cancellation and failures travel along it instead of leaking. Cancellation is cooperative: code has to reach a cancellable suspension point or check for cancellation itself. Flow extends the same model to streams — cold by default, with `StateFlow` and `SharedFlow` for hot, shared values. ### Compile time over run time Where many Java libraries reflect at runtime, Kotlin's ecosystem tends to generate code during compilation: the serialization plugin, KSP processors, reified generics, contracts that feed smart casts. Expect a senior interviewer to ask why.

Nullable type
A type written with a trailing question mark that admits null; the compiler requires a check or a null-handling operator before its members can be used.
Platform type
The type Kotlin assigns to a Java value whose nullability is unknown; the compiler lets you treat it as nullable or non-null and does not check.
Smart cast
Automatic narrowing of a variable's type after a null test or type test, valid only while the compiler can prove the value cannot change in between.
Data class
A class whose primary-constructor properties drive compiler-generated equals, hashCode, toString, copy and componentN functions.
Sealed hierarchy
A class or interface whose direct subtypes are all known at compile time, so a when expression over it can be checked for exhaustiveness.
Value class
A single-property wrapper, annotated JvmInline on the JVM, that the compiler represents as the underlying value where it can, giving a distinct type without an allocation.
Companion object
An object declared inside a class and reached through the class name; Kotlin's stand-in for Java static members, though it is a real instance.
Extension function
A function declared for a receiver type outside that type's source, called with member syntax but resolved statically.
Lambda with receiver
A function literal whose body runs with a given object as this, typed like A.() -> B; the basis of scope functions and DSLs.
Scope function
One of let, run, with, apply and also: small inline helpers that run a block on an object and differ in how they expose it and what they return.
Inline function
A function whose body, together with the bodies of its lambda arguments, the compiler substitutes at each call site, avoiding lambda objects.
Reified type parameter
A type parameter of an inline function that keeps its concrete type at the call site, so the body can use it in type checks and class references.
Declaration-site variance
Marking a type parameter out (produced) or in (consumed) on the class itself, so every use gets the subtyping without use-site wildcards.
Nothing
The bottom type, which has no values; the type of throw and of functions that never return, and a subtype of every other type.
Suspend function
A function that may pause without blocking its thread; it can be called only from a coroutine or from another suspend function.
Structured concurrency
The rule that coroutines live inside scopes whose lifetimes bound them, so cancellation and failures propagate through a parent-child tree.
Dispatcher
The coroutine context element that decides which thread or thread pool a coroutine runs on.
StateFlow
A hot flow that always holds a current value and hands it to each new collector; the usual holder for observable UI or service state.
expect and actual
The Multiplatform mechanism for declaring an API in common code and supplying a platform-specific implementation in each target's source set.
KSP
Kotlin Symbol Processing: an API for annotation processors that reads Kotlin declarations directly, replacing kapt's slower route through generated Java stubs.

The sections stack. The core — fundamentals, null safety, the type system, classes, functions — defines what a value is and how it can be shaped. Functional features and collections sit directly on it: higher-order functions and inline lambdas are what make the collection operators both readable and cheap, and sequences are the same operators made lazy. DSLs are receivers and lambdas pushed to their limit, which is why [Scope Functions](/topics/lang-kotlin-functions-scope-functions) and [Receiver Lambdas](/topics/lang-kotlin-dsls-receiver-lambdas) are two views of one feature. Coroutines reuse all of it. A coroutine builder is a higher-order function taking a suspending lambda with the scope as its receiver; the context is a small keyed set of elements; cancellation travels as an exception. [Flow](/topics/lang-kotlin-flow) is then a suspending producer plus operators that look like the collection ones, so a question comparing Flow operators with list operators is testing whether you see the shared shape and the difference in timing. The outer ring is where Kotlin meets other systems. [Java Interop](/topics/lang-kotlin-interop) is where the null guarantee and final-by-default meet code that shares neither; [Multiplatform](/topics/lang-kotlin-multiplatform) is where common code loses the JDK and leans on the standard library and kotlinx libraries instead. Tooling, testing and serialization are practical consequences: some compiler plugins exist only to relax the language's defaults for frameworks, coroutine tests need their own scheduler because real threads and real time make results nondeterministic, and serialization is code generation rather than reflection. A small example where several core ideas meet: ```kotlin data class User(val email: String, val nickname: String?) sealed interface LoadState { data object Loading : LoadState data class Loaded(val user: User) : LoadState data class Failed(val cause: Throwable) : LoadState } fun LoadState.label(): String = when (this) { LoadState.Loading -> "loading" is LoadState.Loaded -> user.nickname ?: user.email is LoadState.Failed -> cause.message ?: "unknown error" } ``` The sealed interface lets `when` be exhaustive with no `else` branch; each `is` branch smart-casts `this`, so `user` and `cause` are reachable directly; the extension adds `label()` without touching the hierarchy; and the Elvis operator settles the nullable fields. Add a subtype and this `when` stops compiling until it handles the new case — the property interviewers mean when they call sealed types a modelling tool.

  1. Fundamentals →

    Expressions, val-first bindings, types without implicit conversion and the two equality operators are assumed by every other section.

  2. Null Safety →

    Interviewers reach for it earliest; nullable types, the operators and smart casts reappear in almost every later answer.

  3. Classes & Objects →

    The largest everyday surface: constructors, properties, data and sealed classes, objects. Most modelling questions start here.

  4. Functions →

    Extensions, default arguments and scope functions are what make code read as Kotlin rather than translated Java.

  5. Functional Features →

    Lambdas, function types and inline are the machinery that collections, DSLs and coroutines are built from; learn it before them.

  6. Coroutines →

    With the core solid, move to concurrency: suspension, builders and dispatchers, then structured cancellation and exception handling.

  • Sprinkling the not-null assertion operator to silence the compiler: it moves the crash to runtime, and interviewers read it as not understanding Null Safety.

  • Treating values returned from Java as safe: they are platform types, and a wrong assumption surfaces as a crash far from where the null came in.

  • Calling a read-only List immutable: the interface hides mutators, but the object behind it may be a mutable list that another reference still changes.

  • Expecting an extension function to override a member or dispatch polymorphically: it is resolved against the declared type, and a member with the same signature wins.

  • Declaring state in a data class body and expecting it in equality or copy: the generated members see only primary-constructor properties.

  • Launching into GlobalScope to run something in the background: the work escapes every lifecycle, so nothing cancels it and its failure reaches no parent.

  • Catching Exception broadly inside a coroutine without rethrowing the cancellation exception: the coroutine can ignore its own cancellation and keep working after its scope is gone.

  • Making blocking calls on a dispatcher meant for CPU work: each call parks a shared thread and can starve other coroutines; blocking I/O belongs on a dispatcher sized for it.

  • Answering a Flow question with list thinking: a cold flow reruns its producer for every collector, so collecting it twice does the work twice.

This guide assumes Kotlin 2.x, where the K2 compiler is the default. Most language answers read the same on late 1.x releases, but interviewers still ask about the milestones that changed how code is written: - **1.3** — coroutines became stable, and inline classes appeared as an experimental feature. - **1.5** — value classes became the stable form of inline classes, and sealed interfaces arrived. - **1.7.20** — Kotlin/Native switched to its new memory manager by default, retiring the rule that objects had to be frozen before being shared across threads. - **1.9** — `data object` declarations and the `entries` property on enums became stable. - **1.9.20** — Kotlin Multiplatform was declared stable. - **2.0** — K2 became the default compiler, with faster compilation and smart casts that work in more places. The keyword change around inline classes is the one that still confuses candidates reading older material: ```kotlin // 1.3–1.4, experimental inline class OrderId(val raw: String) // 1.5 onward @JvmInline value class OrderId(val raw: String) ``` The idea did not change, only the spelling; when an older answer or article says inline class, read value class.

JetBrains makes the language, its IDE support and the kotlinx libraries for coroutines, serialization and date-time. Interviewers expect you to place Kotlin in three settings. On **Android**, Kotlin is the default language; Jetpack Compose is written for it, and coroutines and Flow are the usual async tools in new code, a role RxJava used to fill. On the **JVM backend**, it runs on Spring Boot, which supports it directly, and on Ktor, JetBrains' own server framework; the Gradle Kotlin DSL is a common first contact. For **shared mobile logic**, Kotlin Multiplatform competes with cross-platform UI frameworks: it shares business logic and lets each platform keep a native UI, with Compose Multiplatform as the option for sharing UI as well. The comparison that comes up most is with modern **Java**. Records, sealed types, pattern matching and virtual threads have narrowed the gap, so a strong answer names what remains: nullability in the type system, extension functions and receivers, and the structured cancellation coroutines give you, which virtual threads alone do not. Scala is the other expressive JVM language a candidate may be asked to contrast it with.

explore

report an issue with this guide →

questions

1,876 · 16 sections

What does 7 / 2 evaluate to in Kotlin, and how do you get a fractional result instead?

level: juniorimportance: must knowfreq 70%
basics
~10 s

7 / 2 is 3, because dividing two whole numbers throws away the part after the decimal point. To get 3.5, make at least one number a decimal, like 7.0 / 2.

open as a page

In Kotlin, is Char a numeric type? How do you get the numeric (code-point) value of a Char, and how do you turn a digit Char like '7' into the Int 7?

level: juniorimportance: must knowfreq 70%
basics
~10 s

No. A Char in Kotlin is a character, not a number. To get its underlying code you use .code, and to turn a digit character like '7' into the number 7 you use .digitToInt().

open as a page

What is `const val` in Kotlin, and how does it differ from a regular `val`?

level: juniorimportance: must knowfreq 70%
basics
~20 s

const val is a value the compiler knows at compile time and copies directly into the code that uses it. A plain val is set when the program runs and is read through a hidden getter method.

open as a page

What is a destructuring declaration in Kotlin, and what does `val (name, age) = person` actually do under the hood?

level: juniorimportance: must knowfreq 70%
basics
~10 s

It unpacks one object into several variables in a single line. Each variable is filled by calling the object's component functions in order: the first gets component1(), the second component2().

open as a page

In Kotlin, what is the difference between == and ===? Which one calls equals()?

level: juniorimportance: must knowfreq 85%
basics
~10 s

== checks if two values are equal (same contents) by calling equals(). === checks if two variables point to the exact same object in memory. Use == for value checks.

open as a page

Why can you use a variable as non-null after calling requireNotNull(x) or checkNotNull(x), even though the null check happens inside a separate function?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Those standard functions tell the compiler a fact: if they return normally, the argument is not null. So after the call the compiler treats the variable as non-null and lets you use it without ?. or !!.

open as a page

What does the Elvis operator ?: do in Kotlin, and what is a typical example of using it?

level: juniorimportance: must knowfreq 80%
basics
~10 s

The Elvis operator ?: gives a fallback value when the left side is null. You write a ?: b: if a is not null you get a, otherwise you get b.

open as a page

A Java method returns a value Kotlin sees as a platform type (e.g. String!). How do you safely give it a default when it is null, and what does the ?: (Elvis) operator do here?

level: juniorimportance: must knowfreq 78%
basics
~10 s

Use the Elvis operator: val name = javaCall() ?: "unknown". If the left side is null, you get the value on the right. It gives a safe default instead of risking a crash.

open as a page

What does `this::myProp.isInitialized` do, and why would you use it on a `lateinit var`?

level: juniorimportance: must knowfreq 55%
basics
~20 s

It checks whether a lateinit property has already been given a value. If you read a lateinit property before it is set, the app crashes; this check lets you ask 'is it set yet?' first and avoid the crash.

open as a page

What is `lateinit var` in Kotlin, and what problem does it solve?

level: juniorimportance: must knowfreq 80%
basics
~10 s

lateinit lets you declare a non-null property without giving it a value right away. You promise to set it later before using it, so you avoid making it nullable.

open as a page

In Kotlin, what is `Any`, and how does it relate to `Any?`? Which one is the true root of the whole type system?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Any is the parent of every non-null type. Any? adds the possibility of null, so it sits above Any and is the top of the whole type system — every value of any type is an Any?.

open as a page

What is the difference between the as and as? cast operators in Kotlin, and what happens when each fails?

level: juniorimportance: must knowfreq 75%
basics
~20 s

as forces a value to a type and crashes with an error if it is not that type. as? tries the same but gives back null instead of crashing when the value does not match.

open as a page

In Kotlin, what does the `out` modifier on a type parameter mean, as in `interface Source<out T>`, and how does it affect assignment between generic types?

level: juniorimportance: must knowfreq 70%
basics
~10 s

out makes the type parameter covariant: the type only produces (returns) values of T, never consumes them. So a Source<Cat> can be used where a Source<Animal> is expected, because every Cat is an Animal.

open as a page

What is JVM type erasure, and what happens to the type argument of a `List<String>` at runtime in Kotlin?

level: juniorimportance: must knowfreq 70%
basics
~10 s

At compile time the type knows it holds Strings, but at runtime the JVM forgets the generic part. A List<String> and a List<Int> are just a plain List to the running program.

open as a page

The JVM erases generics at runtime, so a method that takes a List<T> cannot 'see' what T is. How do you pass the concrete type into a non-inline function so it survives to runtime, and what is the difference between Class<T> and KClass<T>?

level: juniorimportance: must knowfreq 60%
basics
~20 s

You hand the type in by hand as a parameter, like a label. Add a Class<T> or KClass<T> argument so the function knows the real type at runtime. Class is the Java type token; KClass is the Kotlin one.

open as a page

What is an abstract class in Kotlin, and how do you declare an abstract member that subclasses must implement?

level: juniorimportance: must knowfreq 80%
basics
~10 s

An abstract class is one you cannot create objects from directly. It can have members marked abstract that have no body, and any non-abstract subclass must provide their implementation.

open as a page

How do you create a class whose only way to be constructed is through a named factory function on its companion object, hiding the real constructor?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Mark the constructor private and add a function in the companion object that creates and returns the instance. Callers use the named function instead of calling the constructor directly.

open as a page

What is a companion object in Kotlin, and how do you call its members?

level: juniorimportance: must knowfreq 80%
basics
~10 s

It is a special object declared inside a class with the 'companion object' keywords. Its properties and functions can be called using the class name directly, without creating an instance.

open as a page

What is a destructuring declaration in Kotlin, and what makes `val (a, b) = point` work under the hood?

level: juniorimportance: must knowfreq 70%
basics
~10 s

It lets you pull several values out of one object in a single line, like val (x, y) = point. Kotlin does it by calling special functions named component1(), component2(), and so on.

open as a page

What does the generated copy() function on a Kotlin data class do, and why is it useful for immutable data?

level: juniorimportance: must knowfreq 80%
basics
~10 s

copy() makes a new object that is the same as the old one, except for the properties you choose to change. The original stays untouched, so you update data without modifying it in place.

open as a page

What do Kotlin's apply { } and also { } return, and how does each give you access to the object inside the lambda?

level: juniorimportance: must knowfreq 80%
basics
~10 s

Both apply and also return the same object you called them on. Inside apply you use it as this; inside also you use it as it. Neither changes what value comes out.

open as a page

What are default arguments in Kotlin, and how do they let you avoid writing multiple overloads?

level: juniorimportance: must knowfreq 80%
basics
~10 s

A default argument gives a parameter a value used when the caller omits it. So one function with defaults replaces many overloaded functions that differ only by which parameters they accept.

open as a page

In Kotlin, when you call an extension function, what determines which function actually runs: the variable's declared type or the actual object stored in it?

level: juniorimportance: must knowfreq 70%
basics
~10 s

The variable's declared type decides. Kotlin picks the extension function at compile time based on how the variable is typed, not on the real object it holds at runtime.

open as a page

What is an extension function in Kotlin, and how do you declare one?

level: juniorimportance: must knowfreq 85%
basics
~20 s

An extension function lets you add a new function to an existing type without changing its source. You write the type name before the function name, like fun String.shout(), and call it as if it were a normal method.

open as a page

What is a Kotlin extension property, and how do you declare one (e.g. a `lastIndex` for `String`)?

level: juniorimportance: must knowfreq 60%
basics
~10 s

An extension property lets you add a property to an existing type without changing its code. You write it like val String.lastIndex with a custom getter that computes the value.

open as a page

What is the difference between a bound reference like `instance::method` and an unbound reference like `Type::method` in Kotlin?

level: juniorimportance: must knowfreq 55%
basics
~10 s

A bound reference already remembers which object to call the method on, so you just pass arguments. An unbound reference does not; you must pass the object itself as the first argument.

open as a page

What does it mean that a Kotlin lambda 'closes over' a variable, and what can a lambda do with a captured local variable that a Java lambda cannot?

level: juniorimportance: must knowfreq 70%
basics
~10 s

A Kotlin lambda can read and remember variables from the function around it. Unlike Java, it can also change a captured var, not just read it.

open as a page

What does it mean to compose two functions in Kotlin, and how would you write an `andThen` helper that runs one function and feeds its result into another?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Composing means chaining functions so one's output becomes the next's input. An andThen helper takes function f, then g, and returns a new function that does g(f(x)) for any input x.

open as a page

What does the crossinline modifier do on a lambda parameter of an inline function?

level: juniorimportance: must knowfreq 55%
basics
~20 s

crossinline marks a lambda of an inline function so it cannot use a non-local return. It is still inlined, but you are not allowed to write 'return' to exit the calling function from inside it.

open as a page

What does the `::` operator do when written as `list.map(::println)`, and how is it different from writing `list.map { println(it) }`?

level: juniorimportance: must knowfreq 70%
basics
~20 s

::println turns an existing function into a value you can pass around. It does the same job as the lambda { println(it) }, just shorter, because you reuse a function that already exists instead of writing a new one.

open as a page

Given a list of numbers, how do you compute its sum, average, and count in Kotlin, and how do you sum a numeric property of a list of objects?

level: juniorimportance: must knowfreq 75%
basics
~10 s

Use sum() to add numbers, average() for the mean, count() for how many. To sum a field of objects, use sumOf { it.field }, which adds up the chosen value for each item.

open as a page

How do you create an array in Kotlin and read/write its elements?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Use arrayOf(1, 2, 3) to make one, then read or change an element with square brackets like a[0] or a[0] = 9. Get the length with a.size.

open as a page

What does the buildList { } function do, and what is the type of the value it returns?

level: juniorimportance: must knowfreq 55%
basics
~10 s

buildList gives you a temporary mutable list to fill inside the braces, then hands back a normal read-only List. You add items with add(), and the final list cannot be changed afterward.

open as a page

What is the Comparable interface in Kotlin, and what does implementing compareTo give you?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Comparable means a type has a built-in natural order. You write compareTo, which returns a negative number, zero, or positive number. Then you can sort the items and use < and > on them.

open as a page

In Kotlin, what is the difference between accessing a list element with `list[i]`, `list.getOrNull(i)`, and `list.getOrElse(i) { default }`? When does each fail or succeed?

level: juniorimportance: must knowfreq 78%
basics
~10 s

list[i] throws an error if the index is out of range. getOrNull(i) returns null instead of throwing. getOrElse(i) { ... } returns a value you compute when the index is out of range.

open as a page

What does the async coroutine builder return, and how do you get the result out of it?

level: juniorimportance: must knowfreq 80%
basics
~10 s

async starts a background task and hands you a Deferred. You call await() on it to wait for and receive the result value.

open as a page

When you call async { ... } and the block throws an exception, at what point is that exception observed by the caller?

level: juniorimportance: must knowfreq 70%
basics
~10 s

The exception is stored inside the Deferred result and is re-thrown when you call await() on it. Calling async itself does not throw.

open as a page

What is suspendCancellableCoroutine and when do you use it?

level: juniorimportance: must knowfreq 70%
basics
~10 s

It is a helper that turns an old-style callback API into a suspend function. You pause the coroutine, then call resume in the callback to continue with a result, or resumeWithException to fail.

open as a page

You launch a coroutine that runs a tight CPU-bound while-loop, then call cancel() on its Job. The loop keeps running. Why, and what is the simplest fix?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Cancellation is cooperative: the coroutine only stops if it checks for cancellation. A pure CPU loop never checks, so it ignores cancel(). Add a check inside the loop, such as while (isActive).

open as a page

What is a Channel<T> in Kotlin coroutines, and how do producer and consumer coroutines communicate through it?

level: juniorimportance: must knowfreq 70%
basics
~10 s

A Channel is a pipe between coroutines. One coroutine puts values in with send, another takes them out with receive. Both suspend (wait politely) until the other side is ready.

open as a page

What does the buffer() operator do to a Kotlin Flow, and why would you add it to a pipeline?

level: juniorimportance: must knowfreq 70%
basics
~20 s

buffer() lets the part producing values and the part collecting them run at the same time instead of taking turns. Producers can race ahead into a small queue, so a slow collector no longer slows the producer.

open as a page

What does flowOf(...) do, and how does it differ from a list of values?

level: juniorimportance: must knowfreq 60%
basics
~10 s

flowOf takes a fixed set of values and wraps them in a Flow, emitting each one in order when you collect it. A list just holds values; a Flow streams them on demand.

open as a page

What is the flow { } builder in Kotlin, and what does it mean that the flow it creates is 'cold'?

level: juniorimportance: must knowfreq 80%
basics
~10 s

flow { } makes a stream of values. Inside the block you call emit(value) to send each item. Nothing runs until someone collects it. A cold flow re-runs its code fresh for every collector.

open as a page

What is callbackFlow and when would you reach for it instead of the plain flow { } builder?

level: juniorimportance: must knowfreq 70%
basics
~10 s

callbackFlow turns an old-style callback or listener API into a Flow. You use it when values arrive through a callback you register, not from suspending code you call directly.

open as a page

What does the `catch { }` operator do in a Kotlin Flow, and which exceptions can it handle?

level: juniorimportance: must knowfreq 70%
basics
~10 s

catch runs when something fails earlier in the flow (upstream). It only catches errors from the parts above it, lets you log them, and can send a backup value instead of crashing.

open as a page

How do you perform bitwise operations in Kotlin, and how does this differ syntactically from Java?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Kotlin has no &, |, ^, <<, >> symbols. Instead it uses named infix functions like and, or, xor, shl, shr on Int and Long. So you write a and b instead of a & b.

open as a page

Why can you assign to a val exactly once inside a `run { }` lambda and have the compiler accept it as definitely initialized afterwards? What language feature makes this work?

level: juniorimportance: must knowfreq 55%
basics
~20 s

The standard-library functions like run and let promise the compiler that the lambda you pass runs exactly once. Because of that promise, the compiler knows a val you set inside the lambda gets set once, so it treats it as initialized.

open as a page

After calling require(x is String) or x?.let { ... } in stdlib, the compiler often lets you treat x as the narrowed type without an extra cast. What language feature makes the standard library functions like require, check, and requireNotNull propagate type information to the caller?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Kotlin contracts. The stdlib functions declare a promise about how they behave, so the compiler knows that if the call returns normally, a condition is true. It then smart-casts the variable for you.

open as a page

What is the exact operator function signature a class must provide so an instance of it can be used as a custom delegate for a read-only `val` property via `by`?

level: juniorimportance: must knowfreq 55%
basics
~10 s

The delegate needs an operator function named getValue that takes the owner object and the property as parameters and returns the value. For a var you also add a setValue.

open as a page

How do you get the current wall-clock instant in Kotlin's standard library, and what type does it return?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Use kotlin.time.Clock.System.now(). It returns an Instant, which is a single point in time (a timestamp) — not a date or a clock you read on a wall.

open as a page

What does the apply scope function do, and why is it convenient for configuring an object right after you create it?

level: juniorimportance: must knowfreq 78%
basics
~10 s

apply runs a block on an object, lets you set its properties using 'this', and returns that same object. So you can create something and configure it in one expression.

open as a page

What problem does the @DslMarker annotation solve in a Kotlin type-safe builder DSL?

level: juniorimportance: must knowfreq 55%
basics
~10 s

In a nested builder block, methods from the outer block are still callable by accident. @DslMarker hides the outer receiver inside inner blocks, so you only see the members that belong where you are.

open as a page

Explain the roles of the plugins {} and dependencies {} blocks in build.gradle.kts. How do you apply a plugin and declare an implementation dependency?

level: juniorimportance: must knowfreq 65%
basics
~10 s

plugins {} applies Gradle plugins that add build capabilities and tasks. dependencies {} lists the libraries your code needs, grouped by configuration like implementation or testImplementation. You add a library with implementation("group:name:version").

open as a page

What is build.gradle.kts and how does it differ from a build.gradle file?

level: juniorimportance: must knowfreq 70%
basics
~10 s

build.gradle.kts is a Gradle build script written in Kotlin instead of Groovy. Because it is real Kotlin code, the IDE gives autocomplete, type checking, and click-through navigation that the Groovy script cannot.

open as a page

In a kotlinx.html-style DSL like html { body { p { +"hi" } } }, what Kotlin language feature makes the nested blocks work, and why can each block call functions like body or p without a qualifier?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Each block is a lambda that runs 'on' an object (a receiver). Inside the block you can call that object's functions directly, so body() and p() are methods of the current builder.

open as a page

You have a Kotlin class with a companion object containing a function create(). How do you call that function from Java, and why isn't the call simply Foo.create()?

level: juniorimportance: must knowfreq 70%
basics
~10 s

From Java you call Foo.Companion.create(). Kotlin puts companion members on a nested object named Companion, so Java must go through that object rather than calling the method straight on the class.

open as a page

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%
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().

open as a page

You write a Kotlin function fun greet(name: String, greeting: String = "Hello"). A Java colleague says they can only call it by passing both arguments. Why can't Java omit the defaulted parameter, and what is the simplest fix?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Kotlin default values live only in Kotlin metadata, not in the compiled method signature Java sees. So Java must pass every argument. Adding @JvmOverloads makes Kotlin also generate the shorter overloads Java can call.

open as a page

When a Kotlin interface has a method with a body (a default implementation), how is that body compiled for the JVM by default, and what is the DefaultImpls class?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Kotlin lets interface methods have a body. By default the compiler does not put that body on the JVM interface itself; it copies it into a hidden helper class so classes implementing the interface can reuse it.

open as a page

When you call a Java method that takes an int[] from Kotlin, what Kotlin type do you pass, and why not Array<Int>?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Use Kotlin's IntArray for a Java int[]. Array<Int> is an array of boxed Integer objects (Integer[]), which is a different Java type and won't match an int[] parameter.

open as a page

In a Kotlin Multiplatform project, what does `actual typealias UUID = java.util.UUID` do, and why would you use it instead of writing an `actual class`?

level: juniorimportance: must knowfreq 55%
basics
~10 s

It says: on this platform, the shared expect class UUID is exactly the platform's own UUID type. You reuse an existing native type directly instead of writing a wrapper class around it.

open as a page

In a Kotlin Multiplatform module, what artifact does the androidTarget() produce versus the iosArm64()/iosSimulatorArm64() targets, and how does each get consumed?

level: juniorimportance: must knowfreq 62%
basics
~10 s

androidTarget() builds an Android library (an AAR) that Android apps use. The iOS targets build a native framework that an Xcode/Swift app imports. Same Kotlin code, two different output packages.

open as a page

What is the cinterop tool in Kotlin/Native, and what role does a .def file play when binding to a C library?

level: juniorimportance: must knowfreq 55%
basics
~10 s

cinterop is a Kotlin/Native tool that reads C header files and produces Kotlin code so you can call the C library from Kotlin. A .def file tells it which headers and library to use.

open as a page

In a Kotlin Multiplatform project, what is the `commonMain` source set and what kind of code belongs in it?

level: juniorimportance: must knowfreq 70%
basics
~10 s

commonMain holds shared code that compiles to every target (JVM, iOS, JS, etc.). Put platform-independent logic there. It can only use APIs available on all targets.

open as a page

In a Kotlin Multiplatform project, what does it mean that the standard library is available in commonMain, and which kinds of APIs can you safely call there?

level: juniorimportance: must knowfreq 60%
basics
~20 s

commonMain is shared code that compiles to every target. There you can use the common part of Kotlin's standard library — lists, maps, math, random, strings, numbers — but not platform-only things like Java's File or full Java reflection.

open as a page

What is the difference between build.gradle and build.gradle.kts, and what do you gain by choosing the Kotlin DSL?

level: juniorimportance: must knowfreq 70%
basics
~10 s

build.gradle uses the Groovy language; build.gradle.kts uses Kotlin. The Kotlin version is type-checked, so the IDE gives autocompletion, error highlighting, and reliable refactoring before you run the build.

open as a page

You're adding Room to a Kotlin module. Which Gradle dependency configuration do you use to wire up Room's annotation processor, and what else must you add to the build?

level: juniorimportance: must knowfreq 70%
basics
~20 s

You add the Room library as a normal dependency, and put Room's compiler on the ksp configuration (the modern way) instead of a plain dependency. You also apply the KSP Gradle plugin so ksp(...) exists.

open as a page

What does the Kotlin compiler's jvmTarget option control, and what happens if you target a higher bytecode version than the JDK that actually runs your app?

level: juniorimportance: must knowfreq 70%
basics
~10 s

jvmTarget sets which Java bytecode version the compiler produces, like 17 or 21. If you produce bytecode newer than the JVM running it, the app fails to start with an UnsupportedClassVersionError.

open as a page

Kotlin classes are final by default. Why does that break Spring and JPA, and what compiler plugins solve it?

level: juniorimportance: must knowfreq 75%
basics
~20 s

Kotlin classes can't be subclassed unless you write 'open'. Spring and Hibernate need to subclass your classes to add behavior. The all-open and no-arg plugins make the needed classes open and give them an empty constructor automatically.

open as a page

What is detekt and what does running the `detekt` Gradle task do for a Kotlin project?

level: juniorimportance: must knowfreq 62%
basics
~10 s

detekt is a static analysis tool for Kotlin. It scans your source code without running it and reports code smells, overly complex functions, and style problems so you can fix them.

open as a page

Why should a class that launches coroutines take a CoroutineDispatcher as a constructor parameter instead of hardcoding Dispatchers.IO or Dispatchers.Default?

level: juniorimportance: must knowfreq 70%
basics
~10 s

So tests can pass in a fake, controllable dispatcher. If the dispatcher is hardcoded, the test cannot speed up or control timing and must wait for real threads, making tests slow and flaky.

open as a page

In kotlinx-coroutines-test, what are StandardTestDispatcher and UnconfinedTestDispatcher, and how do they differ in when they execute a newly launched coroutine?

level: juniorimportance: must knowfreq 62%
basics
~10 s

Both are test dispatchers using fake time. StandardTestDispatcher waits: a new coroutine just gets queued until you advance time. UnconfinedTestDispatcher is eager: it runs the new coroutine immediately until its first suspension point.

open as a page

What is runTest and why do you use it to test suspend functions instead of runBlocking?

level: juniorimportance: must knowfreq 80%
basics
~10 s

runTest is a helper from kotlinx-coroutines-test that runs a suspend test body. It skips delays using a fake clock, so tests with delay() finish instantly instead of really waiting.

open as a page

What is virtual time in coroutine tests, and why does a delay(10_000) inside runTest finish almost instantly instead of taking 10 seconds?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Coroutine tests use a fake clock. Instead of really waiting, the test scheduler just moves the clock forward, so delays complete immediately and tests stay fast and deterministic.

open as a page

How do you collect all emissions from a finite Flow in a test and assert the exact sequence of values?

level: juniorimportance: must knowfreq 78%
basics
~10 s

Call toList() on the flow inside a runTest block to gather every emitted value into a List, then compare it to the expected list with assertEquals(expected, actual).

open as a page

What types are allowed as parameters of a Kotlin annotation, and which types are NOT allowed?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Annotation parameters can only be simple compile-time values: numbers, Boolean, Char, String, enums, a class reference, another annotation, and arrays of those. You cannot use arbitrary objects like a List or a date.

open as a page

What is a callable reference in Kotlin, and how do you write a reference to a top-level function, a member function, and a property?

level: juniorimportance: must knowfreq 70%
basics
~10 s

A callable reference points at an existing function or property by name using the :: operator, so you can pass it around instead of writing a lambda. Example: list.map(String::length).

open as a page

How do you invoke a function at runtime using Kotlin reflection's KFunction.call(), and what arguments must you pass?

level: juniorimportance: must knowfreq 55%
basics
~20 s

You get a KFunction (for example from ::myFunc or a KClass member) and call its call(...) method, passing the arguments in the same order the function declares them. For a member function, the first argument is the receiver object.

open as a page

In kotlinx.serialization, what does @Contextual do and why would you need it for a type like java.util.Date?

level: juniorimportance: must knowfreq 55%
basics
~10 s

@Contextual tells the serializer: don't pick a serializer at compile time for this property. Look one up at runtime from a registered module. You use it for types you can't annotate, like java.util.Date.

open as a page

In kotlinx.serialization, what is a custom KSerializer and when would you write one by hand instead of relying on the @Serializable-generated serializer?

level: juniorimportance: must knowfreq 60%
basics
~20 s

It is a small class that tells the library exactly how to turn one type into data and back. You write one when the default behavior is wrong, for types you cannot annotate, or when the wire format must differ from your class.

open as a page
Kotlin interview questions & primer · KataJob