iZONE

Kotlin Cheatsheet

A practical Kotlin guide covering syntax, null safety, OOP, coroutines, collections, extensions, and Android development workflows.

Resources

What is Kotlin?

Kotlin is a modern programming language that runs on the Java Virtual Machine. It's the official language for Android development — and honestly, it's a lot cleaner to write than Java.

where kotlin is used

Android developmentprimary use
  • Google's officially recommended language for Android apps.
  • Replaced Java as the standard — most new Android code is Kotlin.
backend / serverserver-side
  • Runs on the JVM — works with Spring Boot and Ktor.
  • Fully interoperable with Java libraries.
Kotlin Multiplatformcross-platform
  • Share code between Android, iOS, and web.
  • Write business logic once — run it everywhere.

your first kotlin program

Kotlin

// every Kotlin program starts here
fun main() {
    println("Hello, Kotlin!")
}

// println prints with a new line
// print prints without a new line
fun main() {
    print("Hello, ")
    print("World!")
    // output: Hello, World!
}

Variables & Data Types

Kotlin has two kinds of variables: ones you can change and ones you can't. The rule of thumb is simple — start with val, switch to var only when you actually need to change the value.

val vs var

Kotlin

// val: cannot be reassigned
val name = "Alice"
// name = "Bob" ← error

// var: can be reassigned
var score = 0
score = 10  // fine
score += 5  // also fine

// Kotlin infers the type automatically
val city = "Colombo"   // String
val age  = 25          // Int
val pi   = 3.14        // Double
val done = true        // Boolean

basic data types

Kotlin

val count: Int     = 42
val big: Long      = 9_000_000_000L
val price: Double  = 19.99
val ratio: Float   = 0.5F
val active: Boolean = true
val name: String   = "Alice"
val grade: Char    = 'A'

// underscores make big numbers readable
val million = 1_000_000

type conversion

Kotlin

val num: Int = 42

// convert to other types
val asLong: Long     = num.toLong()
val asDouble: Double = num.toDouble()
val asString: String = num.toString()

// convert from String
val parsed: Int = "99".toInt()
val safe: Int?  = "abc".toIntOrNull()
// toIntOrNull returns null if it fails
// instead of throwing an exception

// ❌ this does not compile in Kotlin
// val x: Long = 42  ← type mismatch

Strings

String templates are one of the first things Kotlin developers love. Instead of joining strings with +, you embed variables directly inside the text with a $ sign.

string templates

Kotlin

val name  = "Alice"
val score = 95

// simple variable
println("Hello, $name")
// output: Hello, Alice

// expression inside ${}
println("Score: ${score * 2}")
// output: Score: 190

// property access
println("Length: ${name.length}")
// output: Length: 5

// ❌ old Java style (avoid)
println("Hello, " + name + "!")

multiline strings

Kotlin

// triple quotes: no escape needed
val message = """
    Hello, Alice!
    Welcome to Kotlin.
    Enjoy your stay.
""".trimIndent()
// trimIndent removes leading spaces

// raw strings keep everything as-is
val path = """C:UsersAliceDocuments"""
// no need to escape backslashes

common string functions

Kotlin

val text = "  Hello, Kotlin!  "

text.length           // 18
text.trim()           // "Hello, Kotlin!"
text.uppercase()      // "  HELLO, KOTLIN!  "
text.lowercase()      // "  hello, kotlin!  "

val clean = text.trim()
clean.contains("Kotlin")  // true
clean.startsWith("Hello") // true
clean.endsWith("!")       // true
clean.replace("Kotlin", "World")
// "Hello, World!"

clean.split(", ")
// ["Hello", "Kotlin!"]

clean.substring(7, 13)
// "Kotlin"

"".isEmpty()    // true
"  ".isBlank()  // true (blank = only spaces)

escape characters

Kotlin

// common escape sequences
println("Line one
Line two")
// Line one
// Line two

println("Name:	Alice")
// Name:   Alice

println("She said "hello"")
// She said "hello"

println("Path: C:\Users\Alice")
// Path: C:UsersAlice

// tip: use triple quotes to avoid escaping
val path = """C:UsersAlice"""

Control Flow

Kotlin's control flow looks familiar but has a few tricks. if and when can return values — so instead of writing a separate variable assignment, you can write everything in one expression.

if — also an expression

Kotlin

// standard if
val age = 20
if (age >= 18) {
    println("Adult")
} else {
    println("Minor")
}

// if as an expression — returns a value
val label = if (age >= 18) "Adult" else "Minor"

// else-if chain
val score = 75
val grade = if (score >= 90) {
    "A"
} else if (score >= 75) {
    "B"
} else if (score >= 60) {
    "C"
} else {
    "F"
}

when — smarter switch

Kotlin

val grade = "B"

// basic when
when (grade) {
    "A" -> println("Excellent!")
    "B" -> println("Good job!")
    "C" -> println("You passed.")
    else -> println("Try again.")
}

// when as expression
val feedback = when (grade) {
    "A"       -> "Excellent!"
    "B", "C"  -> "Good enough"  // multiple values
    else      -> "Try again"
}

// when with ranges
val score = 82
val result = when (score) {
    in 90..100 -> "A"
    in 75..89  -> "B"
    in 60..74  -> "C"
    else       -> "F"
}

// when without argument (replaces if-else chain)
val x = 15
when {
    x < 0    -> println("Negative")
    x == 0   -> println("Zero")
    x > 0    -> println("Positive")
}

for loops and ranges

Kotlin

// inclusive range: 1 to 5
for (i in 1..5) {
    print("$i ")  // 1 2 3 4 5
}

// exclusive end: 1 to 4 (not 5)
for (i in 1 until 5) {
    print("$i ")  // 1 2 3 4
}

// count down
for (i in 5 downTo 1) {
    print("$i ")  // 5 4 3 2 1
}

// step: every 2nd number
for (i in 0..10 step 2) {
    print("$i ")  // 0 2 4 6 8 10
}

// iterate a list
val names = listOf("Alice", "Bob", "Carol")
for (name in names) {
    println(name)
}

// with index
for ((index, name) in names.withIndex()) {
    println("$index: $name")
}

while and do-while

Kotlin

var count = 0

// while: checks condition first
while (count < 5) {
    println(count)
    count++
}

// do-while: runs at least once
do {
    println("count is $count")
    count++
} while (count < 3)

// break: exit the loop early
for (i in 1..10) {
    if (i == 5) break
    print("$i ")  // 1 2 3 4
}

// continue: skip this iteration
for (i in 1..5) {
    if (i == 3) continue
    print("$i ")  // 1 2 4 5
}

Functions

Functions in Kotlin start with fun. That's not just a keyword — writing Kotlin functions really is more enjoyable than Java. Default parameters alone eliminate a huge amount of boilerplate.

basic functions

Kotlin

// no return value (Unit)
fun greet() {
    println("Hello!")
}

// with parameters
fun greet(name: String) {
    println("Hello, $name!")
}

// with return type
fun add(a: Int, b: Int): Int {
    return a + b
}

// call the functions
greet()            // Hello!
greet("Alice")     // Hello, Alice!
val sum = add(3, 4) // 7

single-expression functions

Kotlin

// standard form
fun square(n: Int): Int {
    return n * n
}

// single-expression form — same thing
fun square(n: Int) = n * n

// works with any expression
fun greet(name: String) =
    "Hello, $name!"

fun max(a: Int, b: Int) =
    if (a > b) a else b

default and named parameters

Kotlin

// default parameters
fun createUser(
    name: String,
    role: String = "user",
    active: Boolean = true
) {
    println("$name | $role | $active")
}

createUser("Alice")
// Alice | user | true

createUser("Bob", "admin")
// Bob | admin | true

// named parameters — skip to the one you need
createUser(name = "Carol", active = false)
// Carol | user | false

// order doesn't matter with named params
createUser(
    active = true,
    role = "editor",
    name = "Dave"
)

vararg — variable number of arguments

Kotlin

// vararg accepts any number of arguments
fun printAll(vararg items: String) {
    for (item in items) println(item)
}

printAll("Apple", "Banana", "Cherry")
// Apple
// Banana
// Cherry

// spread operator: pass an array as vararg
val fruits = arrayOf("Mango", "Kiwi")
printAll(*fruits)

// mix with regular params
fun log(tag: String, vararg messages: String) {
    for (msg in messages) {
        println("[$tag] $msg")
    }
}

log("INFO", "Started", "Connected", "Ready")

Null Safety

Null safety is one of the biggest reasons developers switch to Kotlin. The language forces you to think about null at compile time — so you get an error before the app crashes, not after.

nullable types with ?

Kotlin

// non-nullable: cannot hold null
val name: String = "Alice"
// name = null  ← compile error

// nullable: can hold null
val nickname: String? = null
val city: String? = "Colombo"

// Kotlin forces you to handle the null
// before you can use a nullable value
println(nickname.length)
// ← compile error: nickname might be null

safe call ?. and Elvis operator ?:

Kotlin

val name: String? = null
val city: String? = "Colombo"

// safe call: returns null if name is null
// instead of throwing an exception
println(name?.length)   // null
println(city?.length)   // 7

// Elvis operator: fallback when null
val len = name?.length ?: 0
println(len)  // 0

// chain safe calls
data class Address(val city: String?)
data class User(val address: Address?)

val user: User? = User(Address("Colombo"))
val cityName = user?.address?.city ?: "Unknown"
println(cityName)  // Colombo

non-null assertion !! and smart cast

Kotlin

val name: String? = "Alice"

// !! forces non-null — crashes if null
val length = name!!.length  // 5

// smart cast: Kotlin knows it's non-null
// after an if-null check
if (name != null) {
    // inside here, name is treated as String
    println(name.length)  // no ?. needed
}

// let: run a block only when non-null
name?.let {
    // 'it' is the non-null value
    println("Name is: $it")
    println("Length: ${it.length}")
}

Every !! in your code is a potential crash. If you find yourself using it often, the design probably needs rethinking.

Collections

Kotlin splits collections into two groups: read-only and mutable. This is intentional — it forces you to be clear about whether a list is meant to change or not.

list — ordered collection

Kotlin

// read-only list
val fruits = listOf("Apple", "Banana", "Mango")

fruits[0]         // "Apple"
fruits.first()    // "Apple"
fruits.last()     // "Mango"
fruits.size       // 3
fruits.contains("Banana")  // true

// mutable list
val scores = mutableListOf(10, 20, 30)
scores.add(40)          // [10, 20, 30, 40]
scores.remove(20)       // [10, 30, 40]
scores[0] = 99          // [99, 30, 40]
scores.removeAt(1)      // [99, 40]

// convert between the two
val readOnly = scores.toList()
val mutable  = fruits.toMutableList()

set and map

Kotlin

// set: no duplicate values
val tags = setOf("kotlin", "android", "kotlin")
println(tags)  // [kotlin, android]
tags.contains("android")  // true

val mutableTags = mutableSetOf("a", "b")
mutableTags.add("c")
mutableTags.remove("a")

// map: key-value pairs
val capitals = mapOf(
    "Sri Lanka" to "Colombo",
    "Japan"     to "Tokyo",
    "France"    to "Paris"
)

capitals["Japan"]           // "Tokyo"
capitals.keys               // [Sri Lanka, Japan, France]
capitals.values             // [Colombo, Tokyo, Paris]
capitals.containsKey("France")  // true

// mutable map
val scores = mutableMapOf("Alice" to 90)
scores["Bob"] = 85          // add entry
scores["Alice"] = 95        // update entry
scores.remove("Bob")        // remove entry

iterating collections

Kotlin

val names = listOf("Alice", "Bob", "Carol")

// for loop
for (name in names) {
    println(name)
}

// forEach with lambda
names.forEach { name ->
    println(name)
}

// forEach with implicit 'it'
names.forEach { println(it) }

// with index
names.forEachIndexed { index, name ->
    println("$index: $name")
}

// iterating a map
val scores = mapOf("Alice" to 90, "Bob" to 85)
for ((name, score) in scores) {
    println("$name scored $score")
}

filter, map, find and more

Kotlin

val nums = listOf(1, 2, 3, 4, 5, 6)

// keep only even numbers
nums.filter { it % 2 == 0 }
// [2, 4, 6]

// multiply each by 10
nums.map { it * 10 }
// [10, 20, 30, 40, 50, 60]

// find first even number (or null)
nums.find { it % 2 == 0 }  // 2

// check conditions
nums.any  { it > 5 }   // true
nums.all  { it > 0 }   // true
nums.none { it > 10 }  // true
nums.count { it % 2 == 0 }  // 3

// sort by value
val names = listOf("Carol", "Alice", "Bob")
names.sortedBy { it }
// [Alice, Bob, Carol]

// group into a map
nums.groupBy { if (it % 2 == 0) "even" else "odd" }
// {odd=[1,3,5], even=[2,4,6]}

Classes & Objects

Kotlin classes are much less verbose than Java. A data class with three properties takes one line. You get equals, hashCode, toString, and copy for free.

primary constructor and properties

Kotlin

// class with properties in the constructor
class Person(
    val name: String,
    var age: Int
) {
    // init block runs on creation
    init {
        println("Created: $name")
    }

    // member function
    fun greet() = "Hi, I'm $name"
}

// create an instance (no 'new' keyword)
val alice = Person("Alice", 28)

println(alice.name)    // Alice
println(alice.age)     // 28
alice.age = 29         // var can change
println(alice.greet()) // Hi, I'm Alice

data class — model classes made easy

Kotlin

data class User(
    val id: Int,
    val name: String,
    val email: String
)

val user = User(1, "Alice", "[email protected]")

// toString: readable output
println(user)
// User(id=1, name=Alice, email=alice@...)

// equals: compares values
val user2 = User(1, "Alice", "[email protected]")
println(user == user2)  // true

// copy: change only what you need
val updated = user.copy(email = "[email protected]")
println(updated)
// User(id=1, name=Alice, email=new@...)

// destructuring
val (id, name, email) = user
println("$id $name $email")

object — singleton

Kotlin

// object: single instance, created lazily
object AppConfig {
    val apiUrl = "https://api.example.com"
    val timeout = 30

    fun baseHeaders() = mapOf(
        "Content-Type" to "application/json"
    )
}

AppConfig.apiUrl      // access directly
AppConfig.baseHeaders()

// companion object: class-level members
class User(val name: String) {

    companion object {
        const val MAX_NAME_LENGTH = 50

        // factory function
        fun guest() = User("Guest")
    }
}

val guest = User.guest()
println(User.MAX_NAME_LENGTH)  // 50

secondary constructor and properties

Kotlin

// secondary constructor
class Person(val name: String, val age: Int) {
    constructor(name: String) : this(name, 0)
}

val baby = Person("Max")       // age = 0
val adult = Person("Alice", 28)

// computed property with custom getter
class Circle(val radius: Double) {
    val area: Double
        get() = Math.PI * radius * radius

    val diameter: Double
        get() = radius * 2
}

val c = Circle(5.0)
println(c.area)      // 78.539...
println(c.diameter)  // 10.0

OOP — Inheritance & Interfaces

Kotlin classes are final by default — you have to explicitly mark them open to allow inheritance. That's worth noting, because it's the opposite of Java.

inheritance — open and override

Kotlin

// base class must be 'open'
open class Animal(val name: String) {
    open fun speak() {
        println("$name makes a sound")
    }
}

// subclass
class Dog(name: String) : Animal(name) {
    override fun speak() {
        println("$name barks")
    }
}

class Cat(name: String) : Animal(name) {
    override fun speak() {
        println("$name meows")
    }
}

val dog = Dog("Rex")
dog.speak()   // Rex barks

// call parent function
class Puppy(name: String) : Dog(name) {
    override fun speak() {
        super.speak()  // Rex barks
        println("...softly")
    }
}

abstract class and interface

Kotlin

// abstract class
abstract class Shape {
    abstract fun area(): Double

    // concrete function
    fun describe() = "I am a ${javaClass.simpleName}"
}

class Circle(val radius: Double) : Shape() {
    override fun area() = Math.PI * radius * radius
}

// interface
interface Clickable {
    fun onClick()

    // default implementation
    fun onLongClick() {
        println("Long clicked!")
    }
}

interface Focusable {
    fun onFocus()
}

// implement multiple interfaces
class Button : Clickable, Focusable {
    override fun onClick() {
        println("Button clicked")
    }
    override fun onFocus() {
        println("Button focused")
    }
}

sealed class — restricted hierarchy

Kotlin

// sealed class: all subclasses known at compile time
sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
    object Loading : Result()
}

// when is exhaustive — no else needed
fun handle(result: Result) {
    when (result) {
        is Result.Success ->
            println("Data: ${result.data}")
        is Result.Error ->
            println("Error: ${result.message}")
        is Result.Loading ->
            println("Loading...")
    }
}

val r: Result = Result.Success("Hello")
handle(r)  // Data: Hello

visibility modifiers

Kotlin

class Account(
    val owner: String,
    private var balance: Double
) {
    // public by default
    fun getBalance() = balance

    // only visible inside this class
    private fun validate(amount: Double) =
        amount > 0 && amount <= balance

    // visible in this class and subclasses
    protected fun log(msg: String) {
        println("[Account] $msg")
    }

    fun withdraw(amount: Double) {
        if (validate(amount)) {
            balance -= amount
            log("Withdrew $amount")
        }
    }
}

Lambdas & Higher-Order Functions

A lambda is a function without a name. You pass it directly as an argument. Higher-order functions accept or return other functions — and they show up constantly in Kotlin code.

lambda syntax

Kotlin

// lambda stored in a variable
val double = { x: Int -> x * 2 }
println(double(5))  // 10

// single parameter: use 'it'
val greet = { name: String -> "Hello, $name!" }
println(greet("Alice"))  // Hello, Alice!

// passing lambda to a function
val nums = listOf(1, 2, 3, 4, 5)

// full syntax
nums.filter({ it % 2 == 0 })

// trailing lambda: outside parens
nums.filter { it % 2 == 0 }

// multiple parameters
val add = { a: Int, b: Int -> a + b }
println(add(3, 4))  // 7

higher-order functions

Kotlin

// function that accepts another function
fun operate(
    a: Int,
    b: Int,
    operation: (Int, Int) -> Int
): Int {
    return operation(a, b)
}

val sum     = operate(3, 4) { x, y -> x + y }
val product = operate(3, 4) { x, y -> x * y }
println(sum)      // 7
println(product)  // 12

// function that returns a function
fun multiplier(factor: Int): (Int) -> Int {
    return { num -> num * factor }
}

val triple = multiplier(3)
println(triple(5))  // 15
println(triple(10)) // 30

scope functions — let, run, apply, also, with

Kotlin

data class User(
    var name: String = "",
    var email: String = ""
)

// let: non-null block, 'it' = the value
val name: String? = "Alice"
name?.let {
    println("Name: $it")
    println("Length: ${it.length}")
}

// apply: configure an object, returns it
val user = User().apply {
    name  = "Alice"
    email = "[email protected]"
}

// also: side effect, returns original object
val nums = mutableListOf(1, 2, 3)
    .also { println("Created: $it") }
nums.add(4)

// run: block + return result
val length = name?.run {
    println("Running on: $this")
    this.length  // returned
}

// with: call methods on an object
val result = with(user) {
    "$name <$email>"
}

Extension Functions

Extension functions let you add new functions to any existing class — without touching the original code. That said, they're not magic. They don't actually modify the class.

extension functions

Kotlin

// add a function to String
fun String.shout(): String {
    return this.uppercase() + "!!!"
}

println("hello".shout())  // HELLO!!!

// add a function to Int
fun Int.isEven(): Boolean = this % 2 == 0

println(4.isEven())  // true
println(7.isEven())  // false

// extend a custom class
data class User(val name: String, val age: Int)

fun User.isAdult() = age >= 18

val alice = User("Alice", 25)
println(alice.isAdult())  // true

// extend a nullable type
fun String?.orDefault(default: String): String {
    return this ?: default
}

val name: String? = null
println(name.orDefault("Guest"))  // Guest

extension properties

Kotlin

// extension property — no backing field allowed
val String.wordCount: Int
    get() = this.trim().split(" ").size

val String.isPalindrome: Boolean
    get() = this == this.reversed()

println("hello world".wordCount)   // 2
println("racecar".isPalindrome)    // true
println("kotlin".isPalindrome)     // false

// on a list
val <T> List<T>.secondOrNull: T?
    get() = if (size >= 2) this[1] else null

val nums = listOf(10, 20, 30)
println(nums.secondOrNull)  // 20

Coroutines Basics

Coroutines are Kotlin's way to handle async work — network calls, database reads, anything that takes time. The code looks synchronous, but it doesn't block the thread. That's the whole idea.

suspend functions

Kotlin

import kotlinx.coroutines.*

// suspend: can pause without blocking
suspend fun fetchUser(id: Int): String {
    delay(1000)  // pause for 1 second
    return "User $id"
}

// must be called from a coroutine
suspend fun loadData() {
    val user = fetchUser(1)  // waits here
    println("Loaded: $user") // then continues
}

launch and runBlocking

Kotlin

import kotlinx.coroutines.*

// runBlocking: for main() and tests
fun main() = runBlocking {
    println("Start")

    // launch: runs concurrently
    val job = launch {
        delay(1000)
        println("Coroutine done")
    }

    println("After launch")
    job.join()  // wait for it to finish
    println("End")
}

// output:
// Start
// After launch
// Coroutine done
// End

Avoid GlobalScope in production code. In Android, use viewModelScope (ViewModel) or lifecycleScope (Activity/Fragment) so coroutines cancel automatically.

async and await — get a result back

Kotlin

import kotlinx.coroutines.*

suspend fun loadName(): String {
    delay(500)
    return "Alice"
}

suspend fun loadAge(): Int {
    delay(500)
    return 28
}

fun main() = runBlocking {
    // run both at the same time
    val nameDeferred = async { loadName() }
    val ageDeferred  = async { loadAge() }

    // await: pause until each result is ready
    val name = nameDeferred.await()
    val age  = ageDeferred.await()

    // both finished in ~500ms, not ~1000ms
    println("$name is $age")
}

Tips & Good Habits

These habits make Kotlin code cleaner and safer. Most of them come down to the same principle: use the language features that are there for a reason.

prefer val over var

Kotlin

// ❌ var everywhere — hard to track changes
var userId = 1
var userName = "Alice"
var isAdmin = false

// ✅ val where possible
val userId = 1        // will never change
val userName = "Alice"

// var only when needed
var retryCount = 0
retryCount++

avoid !! — use safe alternatives

Kotlin

val name: String? = getName()

// ❌ crashes if name is null
println(name!!.length)

// ✅ safe call + Elvis
println(name?.length ?: 0)

// ✅ let: only runs if non-null
name?.let { println(it.length) }

// ✅ early return
fun process(name: String?) {
    name ?: return  // exit if null
    // name is non-null from here
    println(name.length)
}

// ✅ requireNotNull: throws with a useful message
fun process(name: String?) {
    val safe = requireNotNull(name) {
        "Name must not be null"
    }
    println(safe.length)
}

Every !! is a crash waiting to happen. If you're writing !! often, the problem is usually that the type should be non-null from the start.

use data class for models

Kotlin

// ❌ regular class: no equals, no toString
class User(val name: String, val age: Int)
val a = User("Alice", 28)
val b = User("Alice", 28)
println(a == b)    // false (different objects)
println(a)         // User@3a4b5c6d (useless)

// ✅ data class: everything for free
data class User(val name: String, val age: Int)
val a = User("Alice", 28)
val b = User("Alice", 28)
println(a == b)    // true
println(a)         // User(name=Alice, age=28)

// copy is especially useful
val updated = a.copy(age = 29)
println(updated)   // User(name=Alice, age=29)
println(a)         // User(name=Alice, age=28)

use when over long if-else chains

Kotlin

// ❌ long if-else chain — hard to read
fun describe(code: Int): String {
    return if (code == 200) {
        "OK"
    } else if (code == 201) {
        "Created"
    } else if (code == 400) {
        "Bad Request"
    } else if (code == 404) {
        "Not Found"
    } else {
        "Unknown"
    }
}

// ✅ when expression — clean and readable
fun describe(code: Int) = when (code) {
    200       -> "OK"
    201       -> "Created"
    400       -> "Bad Request"
    404       -> "Not Found"
    in 500..599 -> "Server Error"
    else      -> "Unknown"
}

handy one-liners worth bookmarking

Kotlin

// repeat a block N times
repeat(3) { println("Hello") }

// takeIf: return value if condition is true
val name = "Alice"
val result = name.takeIf { it.length > 3 }
// "Alice" — condition passed

// takeUnless: return value if condition is false
val short = name.takeUnless { it.length > 3 }
// null — condition was true, so return null

// joinToString: list to formatted string
val items = listOf("A", "B", "C")
items.joinToString(", ")     // "A, B, C"
items.joinToString(" | ")    // "A | B | C"

// getOrElse: safe list access with fallback
val nums = listOf(10, 20, 30)
nums.getOrElse(5) { 0 }      // 0 (index 5 missing)

// also great for debug logging
val user = User("Alice", 28)
    .also { println("Created: $it") }
Was this helpful?

No login required to share feedback

More Cheatsheets

Keep your reference handy

Explore more zero-to-hero cheatsheets for the tools you use daily.