Kotlin Cheat Sheet
Last updated
Hello World & basics
A Kotlin program starts at a top-level main function - no class required.
| Syntax | Meaning |
|---|---|
fun main() { println("Hello") } | Entry point of a program |
println("text") | Print a line to standard output |
print("text") | Print without a trailing newline |
// comment | Single-line comment |
/* comment */ | Multi-line comment |
val input = readLine() | Read a line from stdin (nullable String?) |
val line = readln() | Read a line from stdin (non-null, Kotlin 1.6+) |
Variables (val / var) & types
Prefer val; reach for var only when the value has to change.
| Syntax | Meaning |
|---|---|
val name = "Ada" | Read-only variable, type inferred as String |
var count = 0 | Mutable variable |
val age: Int = 30 | Explicit type annotation |
Int, Long, Double, Float | Numeric types (42, 42L, 3.14, 3.14f) |
Boolean, Char, String | true/false, 'a', "text" |
val big = 1_000_000 | Underscores for readable literals |
"3".toInt(), "2.5".toDouble() | Parse a string into a number |
42.toString() | Number to string |
const val MAX = 10 | Compile-time constant (top level or in an object) |
Strings & templates
String templates replace concatenation almost everywhere.
| Syntax | Meaning |
|---|---|
"Hi, $name" | Insert a variable into a string |
"Total: ${price * qty}" | Insert an expression |
s.length | Number of characters |
s.uppercase(), s.lowercase() | Change case |
s.trim() | Remove leading and trailing whitespace |
s.contains("x"), s.startsWith("a") | Search inside a string |
s.substring(0, 3) | Slice by index range |
s.split(",") | Split into a List<String> |
s[0] | Character at an index |
"""raw text""" | Raw multi-line string, no escaping |
"%.2f".format(3.14159) | Formatted output (3.14) |
Null safety
A type is non-null by default; add ? to allow null, and the compiler makes you handle it.
| Syntax | Meaning |
|---|---|
var s: String? = null | Nullable type |
s?.length | Safe call - returns null if s is null |
s?.length ?: 0 | Elvis operator - fallback value when null |
s!!.length | Not-null assertion - throws if s is null |
if (s != null) s.length | Smart cast to non-null inside the check |
s?.let { println(it) } | Run a block only when not null |
val n = s?.toIntOrNull() | Parse, or null on bad input |
lateinit var x: String | Non-null var initialized later |
Operators
| Operator | Meaning |
|---|---|
+ - * / % | Arithmetic (/ on Ints is integer division) |
+= -= *= /= %= | Augmented assignment |
++ -- | Increment / decrement |
== != | Structural equality (calls equals) |
=== !== | Referential equality (same object) |
< > <= >= | Comparison |
&& || ! | Logical and / or / not |
a in 1..10 | Range or collection membership |
x as Int, x as? Int | Cast / safe cast (null on failure) |
x is String | Type check (smart-casts on success) |
Control flow (if / when)
if and when are expressions - they return a value.
| Syntax | Meaning |
|---|---|
if (a > b) x else y | if as an expression (Kotlin has no ?: ternary) |
if (c) { ... } else if (d) { ... } else { ... } | Chained branches |
when (x) { 1 -> "one"; 2 -> "two"; else -> "other" } | Match a value |
when (x) { 1, 2 -> "low" } | Several values in one branch |
when (x) { in 1..9 -> "digit" } | Match a range |
when (x) { is String -> x.length } | Match a type (with smart cast) |
when { x < 0 -> "neg"; x == 0 -> "zero"; else -> "pos" } | when without a subject, like if/else if |
val label = when (x) { ... } | when as an expression (needs else) |
Loops & ranges
| Syntax | Meaning |
|---|---|
for (i in 1..5) | Inclusive range 1 to 5 |
for (i in 1 until 5) | 1 to 4 (end exclusive) |
for (i in 0..<5) | Same, open-ended range syntax (Kotlin 1.9+) |
for (i in 10 downTo 1 step 2) | Count down in steps |
for (item in list) | Iterate a collection |
for ((i, item) in list.withIndex()) | Index and element together |
for (ch in "abc") | Iterate the characters of a string |
while (cond) { ... } | Loop while true |
do { ... } while (cond) | Run at least once |
break, continue | Exit the loop / skip to the next iteration |
repeat(3) { println(it) } | Run a block n times |
Functions
| Syntax | Meaning |
|---|---|
fun add(a: Int, b: Int): Int { return a + b } | Declare a function |
fun add(a: Int, b: Int) = a + b | Single-expression function, return type inferred |
fun greet(name: String = "world") | Default parameter value |
greet(name = "Ada") | Named argument |
fun log(vararg items: String) | Variable number of arguments |
fun say(): Unit | No return value (Unit is optional) |
val square = { x: Int -> x * x } | Lambda stored in a variable |
fun String.shout() = uppercase() + "!" | Extension function |
fun apply(f: (Int) -> Int) = f(2) | Function as a parameter |
list.map { it * 2 } | Trailing lambda, it is the single parameter |
Lists
listOf is read-only; mutableListOf can change.
| Syntax | Meaning |
|---|---|
val nums = listOf(1, 2, 3) | Read-only list |
val items = mutableListOf("a") | Mutable list |
nums[0], nums.first(), nums.last() | Access elements |
nums.getOrNull(9) | Safe access, null if out of range |
items.add("b"), items.remove("a") | Add / remove |
items[0] = "z" | Replace by index |
nums.size, nums.isEmpty() | Size and emptiness |
x in nums, nums.contains(x) | Membership |
nums.indexOf(2) | Position of an element, -1 if absent |
nums.subList(0, 2) | Slice (end exclusive) |
nums.take(2), nums.drop(1) | First n / all but the first n |
nums.sorted(), nums.reversed() | New sorted / reversed list |
nums.sum(), nums.average(), nums.maxOrNull() | Aggregates |
nums.joinToString(", ") | Join into one string |
Pair(1, "a"), 1 to "a", Triple(1, 2, 3) | Small fixed tuples |
Maps & sets
| Syntax | Meaning |
|---|---|
val m = mapOf("a" to 1, "b" to 2) | Read-only map |
val mm = mutableMapOf<String, Int>() | Mutable map |
m["a"] | Lookup (null if missing) |
m.getOrDefault("z", 0) | Lookup with a fallback |
mm["c"] = 3 | Insert or update |
for ((k, v) in m) | Iterate entries with destructuring |
m.keys, m.values | Keys / values collections |
"a" in m | Key membership |
val s = setOf(1, 2, 2) | Set of unique values ({1, 2}) |
mutableSetOf<Int>() | Mutable set |
Collection operations (lambdas)
| Syntax | Meaning |
|---|---|
list.map { it * 2 } | Transform each element |
list.filter { it > 2 } | Keep matching elements |
list.forEach { println(it) } | Do something with each |
list.any { it > 2 }, list.all { it > 0 } | Does any / every element match |
list.count { it % 2 == 0 } | Count matches |
list.find { it > 2 } | First match or null |
list.sortedBy { it.length } | Sort by a key |
list.groupBy { it.first() } | Group into a Map |
list.distinct() | Remove duplicates |
list.fold(0) { acc, x -> acc + x } | Reduce with a starting value |
list.zip(other) | Pair up two lists |
list.flatMap { it.toList() } | Map then flatten |
Classes & data classes
| Syntax | Meaning |
|---|---|
class User(val name: String, var age: Int) | Class with a primary constructor and properties |
val u = User("Ada", 36) | Create an instance (no new) |
u.name, u.age = 37 | Read / write properties |
data class Point(val x: Int, val y: Int) | equals, hashCode, toString, copy for free |
p.copy(y = 5) | Copy with some properties changed |
val (x, y) = p | Destructuring declaration |
open class Base, class Sub : Base() | Inheritance (classes are final by default) |
override fun toString() = "..." | Override a member |
object Config { val debug = true } | Singleton |
companion object { fun create() = User("", 0) } | Static-like members |
enum class Color { RED, GREEN } | Enum |
sealed class Result | Restricted class hierarchy, exhaustive in when |
interface Shape { fun area(): Double } | Interface |
Error handling
| Syntax | Meaning |
|---|---|
try { ... } catch (e: Exception) { ... } | Catch an exception |
try { ... } finally { ... } | Always run cleanup |
val n = try { s.toInt() } catch (e: NumberFormatException) { 0 } | try as an expression |
throw IllegalArgumentException("bad") | Throw an exception |
require(x > 0) { "x must be positive" } | Argument check (throws IllegalArgumentException) |
check(ready) { "not ready" } | State check (throws IllegalStateException) |
s.toIntOrNull() | Return null instead of throwing |
runCatching { risky() }.getOrDefault(0) | Wrap a call in a Result |
Scope functions
Five small helpers for working with an object inside a block.
| Syntax | Meaning |
|---|---|
x.let { it + 1 } | it is the object, returns the block result |
x.run { this + 1 } | this is the object, returns the block result |
x.apply { field = 1 } | this is the object, returns the object |
x.also { println(it) } | it is the object, returns the object |
with(x) { field } | Not an extension; this is x, returns the block result |
x?.let { ... } | The idiomatic null check + use |
Every piece of Kotlin syntax you reach for, on one page. This Kotlin cheat sheet is a quick reference for the language behind Android and much of the modern JVM - declaring variables, handling nulls safely, branching with when, looping over ranges, writing functions, and working with lists and maps.
Everything here is standard Kotlin and runs on the JVM, Android, and Kotlin Multiplatform alike. Copy what you need, or try it live in the Kotlin playground - paste a snippet, press Run, and see the output in your browser.
Kotlin cheat sheet FAQ
Is this Kotlin cheat sheet free?
when branch, a null-safety operator, or a collection method.What is the difference between val and var in Kotlin?
val declares a read-only reference: it is assigned once and cannot be reassigned. var declares a mutable variable that can be reassigned. Note that val only fixes the reference - a val list = mutableListOf(1) can still have elements added. Kotlin style is to use val everywhere and switch to var only when reassignment is genuinely needed.How does null safety work in Kotlin?
String can never hold null; String? can. The compiler will not let you call a method on a nullable value without handling the null case - with a safe call (s?.length), an Elvis fallback (s?.length ?: 0), a null check that smart-casts (if (s != null)), or, as a last resort, the not-null assertion s!!, which throws a NullPointerException if the value is actually null.When should I use when instead of if in Kotlin?
when whenever you are comparing one value against several possibilities - constants, ranges, types, or a mix - and use if/else for a single yes-or-no condition. Both are expressions, so val label = when (x) { ... } and val label = if (c) a else b are both idiomatic. A when used as an expression must be exhaustive, which usually means adding an else branch (sealed classes and enums can be exhaustive without one).Can I practice Kotlin online?
when, loops, functions, and collections, and issues a free certificate at the end.