Kotlin — Reference
Source: https://kotlinlang.org/docs/home.html
Kotlin
- Created: 2011 (announced by JetBrains; 1.0 released February 2016)
- Latest stable: 2.3.21 (2026-04, bug-fix on the 2.3.20 tooling release; 2.3.0 language release was 2025-12)
- Paradigms: Multi-paradigm — object-oriented, functional, imperative; coroutines for structured concurrency
- Typing: Static, strong, with type inference; null-safety baked in (
TvsT?) - Memory: Garbage-collected on JVM/Android; Kotlin/Native uses a tracing GC since the “new memory manager” (1.7.20+) replacing the legacy reference-count + cycle collector
- Compilation: AOT to JVM bytecode (default), JS, Wasm (alpha/beta), and native via LLVM (Kotlin/Native). K2 compiler became default in 2.0.0 (2024-05)
- Primary domains: Android (Google’s preferred language since 2019), server-side (Ktor, Spring), multiplatform mobile/desktop/web (KMP), build tooling (Gradle Kotlin DSL)
- Official docs: https://kotlinlang.org/docs/home.html
At a glance
- Owner / steward: JetBrains (with the Kotlin Foundation, co-founded with Google).
- Designed to be 100% interoperable with Java; targets JVM 1.8+ by default, with separate backends for Android, JS, Wasm, and native (LLVM).
- Release cadence (since 2.0.0): language releases (
2.x.0) every ~6 months, tooling releases (2.x.20) 3 months later, bug-fixes ad-hoc. (https://kotlinlang.org/docs/releases.html) - LTS-style stability: K2 compiler stable in 2.0.0; binary compatibility across
2.xis strong on JVM. - Major runtimes: HotSpot/OpenJDK, GraalVM, Android ART, Kotlin/Native (LLVM), Kotlin/JS (IR backend), Kotlin/Wasm.
Getting started
-
Install: SDKMAN! (
sdk install kotlin), Homebrew (brew install kotlin), Scoop, Chocolatey, or via IntelliJ IDEA / Android Studio bundle. For multiplatform, use the Kotlin Multiplatform Wizard or IntelliJ. (https://kotlinlang.org/docs/command-line.html) -
Version manager: SDKMAN! is the de-facto choice on macOS/Linux; on Windows, Scoop or kotlinc bundled with the IDE. No “rustup-style” official switcher.
-
Hello world (
hello.kt):fun main() = println("Hello, world!")Compile + run:
kotlinc hello.kt -include-runtime -d hello.jar && java -jar hello.jar. Or usekotlin hello.kt(script mode), orkotlin -script hello.kts. -
Project layout (Gradle / Kotlin DSL):
build.gradle.kts,settings.gradle.kts, sources insrc/main/kotlin/, tests insrc/test/kotlin/. The Kotlin Multiplatform layout addscommonMain,jvmMain,nativeMain, etc. -
Build tool: Gradle is canonical (Kotlin DSL preferred over Groovy DSL); Maven and Bazel also supported. Amper (JetBrains’ newer tool, experimental as of 2026) is gaining traction for KMP.
-
REPL:
kotlinc-jvmopens the REPL; in IntelliJ use Tools → Kotlin → Kotlin REPL.ki(Kotlin Interactive Shell) is a more advanced JetBrains-maintained REPL with autocompletion. (https://kotlinlang.org/docs/command-line.html#run-the-repl)
Basics
- Types/literals:
Int,Long,Double,Float,Boolean,Char,String; unsigned types (UInt,ULong— stable since 1.5). Numeric literals:1_000_000,0xFF,0b1010,1.5e3,1L,1u. - Variables:
val(immutable binding),var(mutable).lateinit varfor late-initialized non-null. Property delegation:by lazy {},by Delegates.observable(...). - Scoping: Lexical, block-scoped. Top-level
val/funallowed (no class wrapper required, unlike Java). - Control flow:
if/whenare expressions (not just statements).whendoes pattern-like matching withis,in, ranges.for (x in 1..10),while,do-while. Labeledbreak@loop/continue@loop/return@lambda. - Functions:
fun add(a: Int, b: Int): Int = a + b. Default args, named args, vararg, single-expression body, top-level functions, extension functions (fun String.shout() = uppercase() + "!"), infix, operator overloading. - Strings: Double-quoted with
$var/${expr}interpolation. Triple-quoted raw strings"""..."""with.trimIndent()/.trimMargin(). - Collections:
listOf,mutableListOf,setOf,mapOf,arrayOf, plus primitive arrays (IntArray). Sequence API for lazy chains. The collections framework distinguishes read-only interfaces (List,Set,Map) from mutable ones — the JVM impl is still ajava.util.ArrayList, so the immutability is compile-time only.
Intermediate
- Type system depth: nullable types (
T?), safe call (?.), Elvis (?:), not-null assert (!!), smart casts afterischecks. Generics with declaration-site variance (out T,in T) and use-site variance. Type aliases. - Sealed class/interface hierarchies for closed sums;
data classfor value semantics (equals/hashCode/copy/componentNsynthesized);value class(formerlyinline class) for zero-overhead wrappers. - Modules: Source-set based via Gradle/IntelliJ. Visibility modifiers:
public(default),internal(module-scoped),protected,private. Java’s JPMS (module-info.java) is supported on JVM since Kotlin 1.2. - Error handling: Exceptions only — Kotlin has no checked exceptions.
try/catch/finallyis an expression.runCatching {}returns aResult<T>.throwis also an expression. - Concurrency: kotlinx.coroutines is the standard answer —
suspend fun,launch,async/await,Flow(cold async streams),StateFlow/SharedFlow. Structured concurrency viaCoroutineScope/SupervisorJob. Channels andselect {}for CSP-style. Threads available viajava.lang.Threadon JVM. - I/O: On JVM, the full Java NIO/IO is available.
kotlinx-iois the multiplatform I/O library (still pre-1.0 as of 2026). - Stdlib highlights:
kotlin.collections(map,filter,fold,groupBy,windowed,zipWithNext,chunked), scope functions (let,run,with,apply,also),kotlin.text(regex, builders),kotlin.time(Duration,TimeSource,measureTime),kotlin.io(file helpers),Result<T>for failure handling.
Advanced
- Memory/GC: JVM uses whichever GC the JVM is configured for (G1 default; ZGC/Shenandoah for low pause). Kotlin/Native shipped a new memory manager in 1.7.20 (stable 1.9) that replaced the strict ownership model with a tracing concurrent GC, removing the previous “frozen object” pain. (https://kotlinlang.org/docs/native-memory-manager.html)
- Concurrency deep dive: Coroutines compile to a continuation-passing-style state machine — every
suspendfunction gets an extraContinuationparameter.Dispatchers.Defaultis a fork-join pool sized to CPU count;Dispatchers.IOis an elastic 64+ thread pool.Flowoperators are cold and run on the collector’s context unlessflowOnshifts upstream. (https://kotlinlang.org/docs/coroutines-overview.html) - FFI: Kotlin/Native uses cinterop to consume C/Objective-C headers (generates a
.deffile → Kotlin bindings). On JVM, use Java’s JNI, JNA, or Project Panama (java.lang.foreign). No FFI on Kotlin/JS (use external/dynamic). - Reflection:
kotlin-reflectartifact (separate jar, ~3 MB) givesKClass,KFunction,KPropertywith full Kotlin metadata. Java reflection still works but loses Kotlin nuances (default args, nullability,data classsynthetics). - Performance tools: YourKit, JProfiler, async-profiler on JVM; IntelliJ Profiler (built on async-profiler since 2023). For coroutines, the kotlinx-coroutines-debug agent +
DebugProbes.dumpCoroutines(). JMH for microbenchmarks via thekotlinx.benchmarkplugin (multiplatform).
God mode
- KSP (Kotlin Symbol Processing): Kotlin’s modern annotation-processing API, ~2x faster than KAPT and multiplatform-aware. KSP2 (stable since Kotlin 2.0) runs in the same compiler process. Used by Room, Dagger/Hilt, Moshi, kotlinx.serialization. (https://kotlinlang.org/docs/ksp-overview.html)
- Compiler plugins: Native FIR-based compiler plugins (K2 era) —
all-open,no-arg,kotlinx.serialization,parcelize,Compose. The Compose plugin rewrites@Composablefunctions to inject theComposerparameter and skip-key remember tables — visible in the K2 IR dump. - Contracts:
kotlin.contracts(still experimental) lets stdlib functions describe their effects so the compiler can smart-cast across boundaries — e.g.,requireNotNull(x)makes the compiler treatxas non-null after the call. - Inline + reified generics:
inline fun <reified T> ...lets generic type info survive erasure at the call site. Combine withcrossinline/noinlineto control non-local returns. - Kotlin/Native memory model: Single-threaded mutability is no longer required (post-1.7.20). Workers use
kotlinx.coroutinesdirectly; the oldfreeze()API is deprecated. - KMP internals:
expect/actualdeclarations resolve at link time;commonMaincompiles to KLib (Kotlin’s portable IR format); platform sources compile to JVM bytecode, JS IR, or native LLVM bitcode. - kotlinx.serialization codegen: the compiler plugin generates a
KSerializer<T>companion at compile time — inspectable via IR dump (-Xphases-to-dump-after=Generation). - R8/ProGuard interplay: Android R8 shrinks/optimizes Kotlin code; coroutines and reflection require explicit
-keeprules. The Kotlin Gradle plugin ships consumer ProGuard rules inkotlin-stdlib. - Value classes:
@JvmInline value class UserId(val raw: Long)— erased to the underlying type at the JVM call site, reducing allocation. Multi-field value classes are previewed in 2.x. - Context receivers / context parameters: Experimental in 1.6.20+, redesigned as context parameters (
context(Logger)) targeted for stable in 2.x — gives “implicit dependency injection” without DI frameworks. Track KEEP-367. - Bytecode peek: Tools → Kotlin → Show Kotlin Bytecode in IntelliJ; the “Decompile” button reverses it back to equivalent Java.
Idioms & style
- Naming:
PascalCasefor types/objects,camelCasefor functions/properties,SCREAMING_SNAKE_CASEforconst val. File names match the dominant top-level class, or useFoo.ktfor utility file containingfun foo(...). - Formatter / linter: ktlint (Pinterest) for formatting + style enforcement; detekt for static analysis; IntelliJ’s built-in formatter follows the official conventions. The Kotlin Coding Conventions (https://kotlinlang.org/docs/coding-conventions.html) are the source of truth.
- Idiomatic patterns: prefer
valovervar; use scope functions sparingly and intentionally (applyfor builder-style mutation,letfor nullable chaining,runfor returning a value); usedata classfor DTOs; exposeList<T>notMutableList<T>from public APIs; structured concurrency over fire-and-forgetGlobalScope. - Expert review focus: misuse of
!!, leakingMutableList, capturing the wrong receiver in scope functions, accidentalSequencere-iteration, blocking calls inDispatchers.Default, swallowingCancellationException.
Ecosystem
- Web/server: Ktor (JetBrains; coroutines-first), Spring Boot (Kotlin support is first-class), http4k, Javalin, Micronaut, Quarkus.
- Android: Jetpack Compose (declarative UI), AndroidX, Hilt (Dagger codegen via KSP), Room, kotlinx.serialization.
- Multiplatform: Compose Multiplatform (JetBrains; iOS/desktop/web/Android), KMP itself, SQLDelight, Ktor client, koin/kodein for DI.
- Data/ML: Kotlin DataFrame, KotlinDL (deep learning), Multik (NumPy-equivalent).
- Testing: JUnit 5, kotest (BDD-style + property testing), Spek, MockK (idiomatic mocking), Strikt (assertions), Turbine (Flow testing).
- Docs: Dokka is the official KDoc-to-HTML/Markdown generator (replaces Javadoc).
- Build: Gradle (canonical), Maven, Bazel, Amper (experimental). Compose Multiplatform packaging via
compose.desktop.application. - Notable users: Google (Android, internal services), Netflix, Atlassian, Square/Cash App, JetBrains itself, Pinterest, Trello.
Gotchas
companion objectis a real singleton, not Java’sstatic.@JvmStaticis required for true static methods callable from Java.lateinit varis null at the bytecode level until set — accessing it pre-init throwsUninitializedPropertyAccessException.List<T>is read-only, not immutable — the underlying object can still be aMutableListcast away;kotlinx.collections.immutableprovides true persistent collections.MutableList<Foo>is invariant — you cannot passMutableList<Subtype>whereMutableList<Supertype>is expected.- Coroutines: catching
Throwablewill swallowCancellationExceptionand break structured concurrency. UsecoroutineContext.ensureActive()or rethrow. ==isequals(value);===is reference identity (opposite of Java).Int?boxes tojava.lang.Integer— beware autoboxing in hot loops.- KAPT is slow and being phased out; migrate to KSP. Some libraries (e.g., older Dagger) still require KAPT.
- Kotlin/Native compile times are long (LLVM); use
kotlin.native.cacheKind=staticfor incremental. data classcopy()is not deep — nested mutable refs are shared.- The
inlinekeyword has three unrelated uses:inline fun(function inlining),inline class(deprecated, nowvalue class), andinline val(compile-time constant property).
Citations
- Kotlin docs home: https://kotlinlang.org/docs/home.html
- Releases & cadence: https://kotlinlang.org/docs/releases.html
- Coding conventions: https://kotlinlang.org/docs/coding-conventions.html
- Coroutines guide: https://kotlinlang.org/docs/coroutines-overview.html
- Kotlin/Native memory manager: https://kotlinlang.org/docs/native-memory-manager.html
- KSP: https://kotlinlang.org/docs/ksp-overview.html
- Compiler plugins: https://kotlinlang.org/docs/all-open-plugin.html
- Multiplatform: https://kotlinlang.org/docs/multiplatform.html
- Command-line + REPL: https://kotlinlang.org/docs/command-line.html
- ktlint: https://pinterest.github.io/ktlint/
- detekt: https://detekt.dev/
- Ktor: https://ktor.io/docs/
- Dokka: https://kotlinlang.org/docs/dokka-introduction.html
- Version verified 2026-05-06: 2.3.21 (2026-04-23)