# Kotlin Cheat Sheet: Syntax, Null Safety and Collections

Source: https://srvscripts.com/guides/kotlin-cheat-sheet/
Updated: 2026-10-09
Publisher: srvScripts (https://srvscripts.com/)

**Short answer:** Kotlin code declares read-only values with `val` and variables with `var`, and allows `null` only in types marked with `?`, handled by `?.` and `?:`. Collections come with `filter`, `map` and `groupBy` built in, `when` replaces switch, and data and sealed classes cut boilerplate. The current release is Kotlin 2.4.20. The tables below show the syntax you will use most, compiled and run on the JVM.

The examples in this Kotlin cheat sheet were compiled with kotlinc 2.4.20 and run on OpenJDK 25.0.4.1 on 9 October 2026. The coroutine examples used kotlinx.coroutines 1.11.0.

## Running Kotlin

| Command | What it does |
| --- | --- |
| kotlinc -version | Compiler version (2.4.20 is the current release) |
| kotlinc main.kt -include-runtime -d app.jar | Compile to a self-contained JAR |
| java -jar app.jar | Run it on any JVM |
| kotlin errs.main.kts arg1 | Run a script directly; args holds the arguments |
| kotlin("jvm") version "2.4.20" | Gradle plugin line in build.gradle.kts for a real project |

A program starts at a top-level `fun main() { println("Hi") }`, with no class needed. Add `args: Array<String>` to read command-line arguments.

## Variables, types and null safety

| Syntax | What it does |
| --- | --- |
| val host = "web01" | Read-only (prefer this) |
| var port = 443 | Mutable; the type (Int) is inferred and fixed |
| val big = 10_000_000_000L · val load: Double = 0.75 | Long literal · explicit type |
| 7 / 2 · 7.0 / 2 | 3 (integer division) · 3.5 |
| "42".toInt() · "x".toIntOrNull() | Parse (throws) · parse or null |
| var maybe: String? = null | Only types ending in ? can hold null |
| maybe?.length | Safe call: null instead of an exception |
| maybe?.length ?: 0 | Elvis operator: fallback when the left side is null |
| maybe?.let { println(it) } | Run a block only when not null |
| maybe!!.length | Assert not null; throws NullPointerException if it is |
| x as? Int | Safe cast: null if the type does not match |
| if (maybe != null) maybe.length | Smart cast: after the check, maybe is treated as String |

## Strings

| Syntax | What it does |
| --- | --- |
| "$host:$port" · "${host.uppercase()}" | String templates: a name, or any expression in braces |
| "%.1f%%".format(load * 100) | printf-style formatting |
| s.trim() · s.split(",") · list.joinToString("-") | Trim · split to a list · join |
| s.substringBefore('.') · s.substringAfterLast('.') | web01 from web01.example.com · file extension |
| s.take(2) · s.takeLast(2) · s.padStart(3, '0') | First or last characters · pad |
| "error" in s · s.equals(t, ignoreCase = true) | Contains · case-insensitive compare |
| s.replace(Regex("\\d"), "#") | Regex replace |
| buildString { append("a"); append(1) } | Build a string efficiently |

```
val json = """
    {
      "host": "$host",
      "port": $port
    }
""".trimIndent()                       // raw string with templates; indentation removed

val tpl = $$"""{"price": "$10", "host": "$$host"}"""   // multi-dollar: only $$ interpolates
```

## Collections

| Syntax | What it does |
| --- | --- |
| listOf("a", "b") · mapOf("ssh" to 22) · setOf(1, 2) | Read-only collections |
| mutableListOf() · mutableMapOf() | Mutable versions |
| list += "web03" · list.remove(x) | Add and remove on a mutable list |
| list[0] · list.first() · list.last() · list.getOrNull(9) | Read by index; getOrNull avoids an exception |
| map["mysql"] = 3306 · map.getOrPut("redis") { 6379 } | Write · read or insert |
| for ((k, v) in map) | Iterate with destructuring |
| nums.filter { it > 2 }.map { it * 10 } | Filter and transform; it is the single parameter |
| nums.sum() · nums.maxOrNull() · nums.count { it % 2 == 0 } | Aggregates |
| nums.sorted() · hosts.sortedBy { it.length } | Sorted copies |
| hosts.groupBy { it.take(2) } | Map of key to list |
| hosts.groupingBy { it.take(2) }.eachCount() | Count per key |
| hosts.associateWith { it.length } | Map from each item to a value |
| nums.partition { it > 2 } · nums.chunked(2) | Split in two · batches |
| a intersect b · a union b · a subtract b | Set operations |
| 0 until 3 · 0.. "ok"
    301, 302 -> "redirect"
    in 400..499 -> "client error"
    else -> "server error"
}

fun describe(x: Any?): String = when (x) {
    null -> "null"
    is Int if x > 1000 -> "big int"                 // guard condition
    is Int -> "int $x"                              // smart cast to Int
    is String -> "string of ${x.length}"
    else -> "other"
}
```

Loops use `for (i in 0 until 3)`, `while` and `do ... while`. Labels such as `outer@` with `break@outer` or `continue@outer` control nested loops. A `when` over a sealed type or enum needs no `else`, because the compiler checks that every case is covered.

## Functions, lambdas and scope functions

| Syntax | What it does |
| --- | --- |
| fun connect(host: String, port: Int = 22): String | Default arguments |
| connect("db01", timeout = 1000) | Named arguments, in any order |
| fun add(a: Int, b: Int) = a + b | Single-expression function |
| fun sum(vararg n: Int) = n.sum() | Variable number of arguments |
| fun String.isPrivateIp(): Boolean = startsWith("10.") | Extension function on an existing type |
| val square: (Int) -> Int = { it * it } | Lambda with a function type |
| retry(3) { ping() } | Trailing lambda: the last lambda argument goes outside the brackets |
| String::length | Function reference |
| fun  maxOf3(a: T, b: T, c: T): T | Generic function with a bound |

| Scope function | Object inside | Returns | Typical use |
| --- | --- | --- | --- |
| x.let { ... } | it | Lambda result | Null checks with ?.let, transforms |
| x.apply { ... } | this | x | Configure an object after creation |
| x.also { ... } | it | x | Side effects such as logging |
| x.run { ... } · with(x) { ... } | this | Lambda result | Compute a value from an object |

## Classes, data classes and sealed types

```
data class Server(val name: String, val ip: String, val port: Int = 22) {
    init { require(port in 1..65535) { "bad port: $port" } }
    val address get() = "$ip:$port"
}
val srv = Server("web01", "10.0.0.5", 443)
val copy = srv.copy(port = 8443)            // equals, hashCode, toString, copy are generated
val (name, ip) = srv                        // destructuring

sealed interface Result {
    data class Ok(val value: Int) : Result
    data class Err(val message: String) : Result
    data object Pending : Result
}

class Db(val host: String, private val port: Int = 3306) {
    companion object { fun local() = Db("localhost") }   // like static members
    var status = "down"
        private set                                       // public read, private write
}

enum class Level(val code: Int) { INFO(1), WARN(2), ERROR(3) }
object Registry { val items = mutableListOf() }  // singleton
@JvmInline value class Port(val value: Int)              // type-safe wrapper, no allocation
```

Classes and members are `final` by default; mark them `open` to allow inheritance and use `override` in the subclass. Visibility is `public` unless you say `private`, `protected` or `internal` (same module).

## Exceptions and coroutines

```
fun parsePort(v: String): Int = v.toIntOrNull() ?: throw ConfigException("bad port: $v")

val p = try { parsePort("80") } catch (e: ConfigException) { -1 }   // try is an expression

val res = runCatching { parsePort("x") }
res.getOrDefault(22)                    // 22
res.exceptionOrNull()?.message          // "bad port: x"

require(port > 0) { "port must be positive" }   // IllegalArgumentException
check(connected) { "not connected" }            // IllegalStateException
error("boom")                                   // IllegalStateException
```

Kotlin has no checked exceptions, so nothing forces you to catch. Coroutines need the `org.jetbrains.kotlinx:kotlinx-coroutines-core` library:

```
suspend fun check(host: String): String { delay(10); return "$host ok" }

fun main() = runBlocking {
    val results = listOf("web01", "web02").map { h -> async { check(h) } }.awaitAll()
    println(results)                                     // [web01 ok, web02 ok]
    val r = withTimeoutOrNull(2_000) { check("db01") }   // null if it takes too long
}
```

## For server admins: files, processes and scripts

| Syntax | What it does |
| --- | --- |
| File("app.log").readText() · .readLines() | Whole file · list of lines (small files) |
| file.useLines { lines -> lines.count { "ERROR" in it } } | Stream a large file and close it automatically |
| file.forEachLine { ... } | Process line by line |
| file.writeText(s) · file.appendText(s) | Overwrite · append |
| File("demo").mkdirs() · file.exists() · file.length() | Create directories · test · size |
| dir.walk().filter { it.extension == "log" } | Recursive search |
| ProcessBuilder("df", "-h", "/").redirectErrorStream(true).start() | Run a command without a shell, then waitFor() |
| Regex("""^(\S+) .*" (\d{3}) """).find(line)?.destructured | Pull the IP and status from an access-log line |

For small admin tasks, a `.main.kts` script runs with `kotlin errs.main.kts` without a build tool. It can import any JDK class, so `java.io.File`, `ProcessBuilder` and `java.net.http.HttpClient` are all available.

**Official documentation (checked 9 October 2026):** [Kotlin: Basic syntax overview](https://kotlinlang.org/docs/basic-syntax.html) · [Kotlin: Null safety](https://kotlinlang.org/docs/null-safety.html) · [Kotlin: Collections overview](https://kotlinlang.org/docs/collections-overview.html) · [Kotlin: Coroutines basics](https://kotlinlang.org/docs/coroutines-basics.html) · [What’s new in Kotlin 2.4.20](https://kotlinlang.org/docs/whatsnew2420.html)

## Kotlin Cheat Sheet at a glance

In short: A compact Kotlin 2.4 reference covering syntax, null safety, collections, classes, coroutines and file handling, with every example compiled by kotlinc 2.4.20.

Kotlin Cheat Sheet: what this guide covers.

**Related guides:** [Java Cheat Sheet: Syntax, Collections, Records and Streams](https://srvscripts.com/guides/java-cheat-sheet/) · [Swift Cheat Sheet: Syntax, Optionals, Protocols and async](https://srvscripts.com/guides/swift-cheat-sheet/) · [Dart 3 Cheat Sheet: Null Safety, Records, Patterns and async](https://srvscripts.com/guides/dart-cheat-sheet/).
